《AI 辅助软件工程:实践与案例解析》前言

2024 年 6 月 1 日,我计划利用在 Thoughtworks 的三个月年资假做一些 AI 辅助研究与超前设计。同时结合之前的 AI 辅助软件工程实践经验以及在 Thoughtworks 的开源项目与落地经验,编写一本关于《AI辅助软件工程》的开源电子书。

  • 作为一个新晋奶爸,我需要在带娃的业余时间里完成这本书,所以有些调研会比较仓促和写作进度可能会比较慢。但是,我会尽量保证每周至少更新一篇文章。
  • 作为一个工程师,我更喜欢能真正落地的方案,而不是纸上谈兵。所以,我花了大量的时间在收集和分析落地案例,以及在实际项目中的实践经验,以避免浪费读者的时间。

这本开源电子书( https://aise.phodal.com/ )包含了什么:

  • 国内外最新的 AI 辅助软件工程实践。我们阅读了大量的国内外生成式 AI 技术博客,收集了从 GitHub、GitLab、Google、JetBrains、Atlassian、New Relic/Dynatrace 等公司的 AI 辅助软件工程实践。
  • 从 AI 模型到 IDE 插件的实现细节。作为 IDE 插件 AutoDev 开源项目以及 Shire 编码智能体语言的作者,我会结合实际项目经验,分享如何从 AI 模型到 IDE 插件的实现细节。
  • 从编码 RAG 到编码智能体的实践案例与经验。我们收集了大量的编码智能体的实践案例与经验,以及在编码领域如何使用 RAG 模型的实践案例。

这本书没有什么?

  • 相关 Paper。作为一个工程师,我更喜欢能真正落地的方案,而不是纸上谈兵。尽管已经有大量的 AI 辅助软件工程的 Paper,从业内的实践经验来看,Paper 与实际落地的差距还是很大的。

如果你对此感兴趣,欢迎加入这个开源项目。

阅读需知:

在大多数组织中,开发者用于编码的时间不到总工作时间的 40%,因此编码提效对整个软件开发生命周期(SDLC)的效能影响很有限,应尝试将 AI 应用于软件 全生命周期和整个团队,而不仅仅是个别成员、个别环节的产出。

更多关于我的信息,请访问我的个人网站:Phodal。或者扫描下方二维码:

简介

本书是一本关于如何使用 AI 辅助软件工程的开源电子书。我们将介绍:

  • 如何使用生成式 AI 来在软件工程的不同阶段进行辅助。
  • AI IDE 编程工具的 Prompt 技巧。
  • 设计 AI 辅助流程来提高软件工程师的工作效率。
  • 定制 AI IDE 来融入不同编程任务。
  • 设计和构建 AI 编码智能体。
  • 如何使用 Shire 与 RAG 来进行 AI 辅助研发。

开始阅读之前,你需要自行了解一些基本概念:

  • 什么是生成式 AI?
  • AI 智能体是什么?
  • 什么是 IDE 插件?(我想你是不需要的)

本书不适合以下人群:

  • 想要了解 AI 基础知识的人。
  • 快速入门使用 AI 辅助软件工程的人。
  • 想要了解 AI IDE 插件开发的人。

如果你是以上人群,建议你先了解一些基础知识,然后再来阅读本书。

AI 辅助软件工程:AI4SE 的 2024 趋势

AI4SE(Artificial Intelligence for Software Engineering)是指人工智能技术应用于软件工程领域,旨在通过利 用AI 算法和工具来改进软件开发、 维护、测试和管理等各个环节的效率和效果。AI4SE的核心目标是通过自动化和智能化技术,降低软件开发的复杂性,提高软件的质量,并加速软件工程过程。

从 2024 年的视角回顾,与 2023 年相比,AI 在软件工程中的应用已经变得更加广泛和深入。这一趋势体现在AI编程工具的进化上,主要体现在以下几个方面:

  1. 全面探索:从辅助开发人员到全生命周期
  2. 演进路径:个体、团队、组织
  3. 形态变化:从本地 AI IDE 到领域特定的智能代码生成

站在全球来看,在不同的国家、区域人们的关注点是不一样的,比如在中国,人们更关注于如何提高软件工程师的工作效率,而在其它一些区域,人们更关注于如何 提高软件工程的质量、如何辅助进行遗留系统的迁移。 除了各自所处的数字化阶段、水平不同,还存在一些技术人才数量、质量、分布等方面的差异。

全面探索:从辅助开发人员到全生命周期

AI 技术已经从简单的辅助开发人员发展到涵盖软件开发的整个生命周期。在这一过程中,AI 工具的应用范围不断扩展,从需求分析到运维管理,每个阶段都得到了显著提升。

单工具 Copilot

下图是,Thoughtworks 在 2023 年初对 AI 辅助软件工程的流程分析,即在软件开发的不同阶段,AI 可以提供哪些辅助功能:

AI DevOps 流程

从 2022 年 GitHub Copilot 的发布,我们可以看到越来越多的 AI 工具开始涉足到软件开发的不同阶段。

就 2023 年的结论而言,基于人工智能的工具与基础大语言模型可以增强软件开发在设计、 需求、测试、发布和运维等各个环节中的能力,提高质量和效率。 但是,这些工具往往是破碎、割裂的,还可能并不适合我们现有的研发流程。

AI 原生的研发工具

在市场上,我们也可以看到市面上的主流研发工具,如 JetBrains、GitHub(网站)等,都在逐渐加入 AI 功能,使得 AI 功能逐渐融入到我们的日常工作中。

AI Native 工具

在 IntelliJ IDEA 中,我们可以看到 AI 功能的加入,如:

  • 原生的向量化模型
  • 基于语义化搜索(SearchEverywhere)
  • 结合补全统计的机器学习补全插件:Machine Learning Code Completion
  • 适用于单个代码行的 Full Line Code Completion
  • 等等

而除了 GitHub Copilot 工具本身,其也开放了其插件能力,使得我们可以定义自己的 AI 智能体,以适应我们自己的工作流程:Chat extensions

多阶段协同

在 2024 年,我们可以更多的变化,诸如:

  • 在智能运维领域,AI 可以结合判别性 AI 分析日志,生成式 AI 分析原因,再结合智能体跟据运行错误,自动修代码复问题等
  • 在测试领域,AI 除了辅助进行测试用例的生成,还可以生成对应的单元测试代码,甚至是自动化测试代码。
  • 在 UI 设计领域,AI 可以直接生成对应的代码,基于提示词来修改 UI,所生成的是最终的 UI 代码,而不是设计稿。
  • ……

如下是 Dynatrace 的 Davis AI 示例:

hypermodal AI

Dynatrace 的 Hypermodal AI(超模态人工智能),是一种将多种类型的人工智能整合在一起,以增强可观察性和安全解决方案的高级方法。 这个概念结合了三种不同的AI模式:

  1. 预测AI:使用历史数据和观察到的模式来预测未来的行为和需求。这对于在问题发生之前预见并防止潜在问题至关重要。
  2. 因果AI:专注于实时分析富有上下文的数据,以确定问题的根本原因并自动化风险缓解。这种类型的AI通过理解系统内的依赖关系和交互,提供精确的答案。
  3. 生成AI:利用高级算法来创建针对特定问题的建议和解决方案。通过提供上下文相关的建议和使用自然语言处理自动化任务,这种AI增强了用户互动。

通过融合这些AI功能,超模态AI为管理复杂的软件环境提供了更全面和有效的解决方案。Dynatrace 的 Davis AI 平台通过整合预测 AI、因果 AI 和生成 AI, 提供实时洞察、自动化和增强的数字服务安全性。

诸如此类的变化,使得 AI 所能辅助的范围更加广泛,从而使得 AI 在软件工程中的应用更加全面。

演进路径:个体、团队、组织

从企业采用 AI 的路径来看,我们会发现:越来越多的组织开始探索在组织层面使用 AI 辅助整体软件研发。因而,AI 辅助研发组织的技术蓝图便也逐渐清晰起来:

AI for Org

从形态上可以分为:带扩展能力的 IDE 插件、团队 AI 助手、 结合 AI 的内部 IM,以及作为基础能力的 Chatbot。

个体辅助 IDE 插件示例:AutoDev

AI 编程工具应该怎么设计才能提效?在当前来说,国内的环境下,由于我们的目标是实现可见的效率提升,即要通过可度量的指标。因而,可以看到一些明显 的变化:

  1. 代码补全与生成是最容易度量的指标,并且市面上也以此类为主。
  2. 在不同环节,从时间角度来计算,如代码审查、代码测试等。
  3. 结合代码的问答,以减少工具切换、复制粘贴,提高效率。

如下是我们开源的 IDE 插件 AutoDev 的能力全景图:

AutoDev 能力全景

由于过去的 AI 编程工具主要面向的是个体开发者,而随着探索进入一些深入区,以及实践的不断推进。所以,在结合组织能力的情况下,我们可以看到:

  • 多样的 AI 工具正在融入自己的开发流程中
  • AI 工具开始融入内部的一系列规范
  • 不断结合内部知识库,提升内容生成的质量
  • 开始构建自己的场景化能力

故而,我们将其总结为,从个体到团队,再到组织,并开始思考如何扩大 AI 的应用范围。

团队 AI 助手示例:Haiven

在设计团队 AI 助手时,我们需要考虑到团队的拓扑结构,以及团队的工作流程。如下图所示:

团队拓扑

在一个组织中,必然会有大量的不同类型的团队,每个团队受限于业务盈利模式等因素,其采用的技术、工作流程等都会有所不同。诸如于,核心的业务部门可以 享受自己特有的开发流程,而其它非核心部门则会采用一些标准化的流程。

考虑到盈利水平高的部门,通常是大型团队,他们不仅可能有自己的 AI IDE 插件,还会有自己的 AI 团队。因此,我们也建议设计一个可以让不同团队共享知识的 AI 团队助手。

诸如于 Haiven™ 团队助手:

Haiven™ 团队助手 是由 Thoughtworks 开发的一款 AI 驱动工具,旨在增强软件开发流程。它与现有的 AI 编码助手集成,并提供可插拔的知识包,帮助团队完成开发任务、加速反馈循环,并推动创新。Haiven 支持多种云和身份提供商,便于采用并集成到现有工作流程中。 它支持研究、用户旅程分析、 架构开发和团队知识编码,从而提升生产力、质量和团队能力,同时保持对 AI 环境的控制。

  • 提高软件开发的生产力和质量。可复用提示词(prompt)可以将最佳实践和即时知识融入团队的工作流程,以减少浪费,提升开发者满意度,并保持软件质量始终如一。
  • 动态增强团队成员能力。Haiven 增强了团队的自然人类创造力,使他们能够轻松研究用户需求,探索创新功能并交付卓越的用户体验。
  • 易于采用。支持多云和身份提供商,以及可根据团队工作流程定制的可插拔知识包,Haiven 极易被采用和集成。
  • 理解今天的 AI 的潜力。AI 市场是动态且迅速发展的,许多工具并未专门针对软件开发任务设计,或者只关注有限的功能范围。Haiven 提供了一个简单的沙盒,用于今日试验新功能。

通过基础的 AI 赋能,让不同团队在有能力的情况下,可以根据自己的需求,定制自己的 AI 助手。

组织级 IM/Chatbot 示例

回到整体组织层面,我们也会看到内部的 IM 工具也在融合 AI 功能,以提升协作体验。诸如于:

  • 寻找负责人/专家:通过 AI 助手,可以快速找到组织内的专家,以解决问题。
  • 运维 Chatbot,辅助分析部署失败问题,可以自动化运维任务,如自动化部署、自动化监控等。
  • CI/CD 问题分析:通过 AI 助手,在尝试修复问题时,还可以告知问题的可能根因。
  • AI 会议创建与管理。通过 AI 助手,可以自动创建会议,自动邀请参会人员,自动记录会议内容,自动提醒会议时间等。

如下是 Teams Copilot 的示例:

在另外一方面,我们也会有大量的其它 Chatbot 在不同的研发团队中使用,诸如于辅助平台的使用、文档查找等等。

形态变化:从本地 AI IDE 到领域特定的智能代码生成

与通用性的 AI 辅助相比,领域特定的 AI 辅助效果更好,因为它更了解领域的特点,更容易生成符合领域规范的代码。从智能代码生成的角度来看,由于过去包含 大量的语料知识,生成的代码质量更高,更符合领域规范。

IDE 即 AI 辅助研发中心

在前面,我们已经看到了 AI 辅助研发中心的概念,即在一个组织中,AI 辅助研发中心可以为不同团队提供 AI 能力,以提升整体的研发效率。

还需要注意的是,AI 在快速生成大量代码的同时,也会带来一些问题,如代码质量、安全性等。我们需要考虑如何在 AI 生成代码的同时,保证代码的质量。如下图 所示:

我们需要考虑构建类似于 SonarLint 的体系化质量检查 工具,以保证 AI 生成的代码质量。

AI 增强的低代码平台

诸如低代码应用程序平台 Appian 的分析文章 ,生成式 AI 与低代码平台结合,可以在多个方面实现增强的生产力和创新:

  1. 文本生成与聊天机器人: 结合生成式 AI 和低代码平台,能够快速部署聊天机器人,处理基本的客服请求或生成待人审阅的电子邮件草稿,从而简化沟通流程。
  2. 从 PDF 构建界面: 生成式 AI 能够解析 PDF 设计并将其转换为功能性界面或表单。结合低代码平台,确保设计到代码的准确转换,无需额外校对。
  3. 工作流程自动生成: 通过生成式 AI 增强的低代码平台,可以快速生成复杂的工作流程,包括视觉图表和可执行代码。这对于例如账单管理等任务至关重要,用户反馈后能快速进行迭代改进。
  4. 自助式分析: 利用自然语言处理的 AI 驱动平台,团队能够快速从数据源生成报告和洞察。AI 与低代码的结合,使得能够灵活调整流程和操作,提升业务效率和决策能力。

除了上述的经典场景之后,我们也可以看到多模态 AI 代码的生成,诸如于 Google 的 ScreenAI

它可以将图像和文本结合起来,生成对应的 DSL,进而转换成不同的代码。

You only speak JSON. Do not write text that isn’t JSON.
You are given the following mobile screenshot, described in words. Can you generate 5 questions regarding the content of
the screenshot as well as the corresponding short answers to them?

The answer should be as short as possible, containing only the necessary information. Your answer should be structured
as follows:
questions: [
{{question: the question,
answer: the answer
}},
...
]

{THE SCREEN SCHEMA}

当然了,为构建这样的语料,你还需要生成大量的页面与低代码数据。

从云 IDE 到智能云开发环境

在云 ☁️ 时代,大型组织构建了大量的云 IDE 和云基础设施,以尝试卖出更多的云服务以及解决最后一公里的部署问题。尽管,受限于云 IDE 能力、网络与计算能力, 云 IDE采用并不高,但是随着 AI 的发展,我们可以看到更多的智能云开发环境的出现。

虽然..但是..,我们非常看好诸如 v0.dev 这一类针对于领域特定的开发工具。

v0.dev

它可以:

  • 高效 UI 生成:通过输入提示词快速创建前端组件和页面。
  • 一键定制化组件:少量的提示词即可创建优雅复杂的组件,一键导出并应用于项目。
  • 快速原型设计:提供即用生产代码,适用于新旧项目,项目较大时需整理代码结构。
  • 图生成代码:通过图形化界面生成代码,适用于新手,不熟悉代码的人员。

它可以快速帮助我们构建出一个原型,然后再进行。再结合其它 AI 工具,如代码审查、代码测试等,可以大大提高我们的开发效率。

还有诸如 Google Project IDX 这一类 AI 辅助型工作区。IDX 支持众多框架、语言和服务, 还与 Google 产品集成,可简化您的开发工作流程,让您可以快速、轻松、高效地跨平台构建和发布应用。

IDX Demo

尽管 IDX 还非常早期,但是我们可以看到,未来的云 IDE 将会更加智能化,更加适应我们的工作流程。

在国内,我们也可以看到 Babel Cloud、MarsCode 等一系列云 IDE 工具,也在不断的发展中。

其它

AI 在软件工程中的应用已经从辅助开发人员扩展到整个开发生命周期,逐步演进为团队和组织层面的协作工具,并在工具形态上实现了从本地 AI IDE 到领域特定智能代码生成的转变。这些变化不仅提高了开发效率和质量,还推动了整个软件工程领域的发展。

  1. 全面探索:AI 从辅助开发人员扩展到覆盖软件开发的整个生命周期,从需求分析到运维管理,每个阶段都显著提升了效率和质量。
  2. 演进路径:AI 工具从个体使用扩展到团队和组织层面。个体使用的 AI 工具如 AutoDev,团队助手如 Haiven,以及组织层面的 AI 集成到内部 IM 和 Chatbot 系统中,全面增强了协作和效率。
  3. 形态变化:从本地 AI IDE 发展到领域特定的智能代码生成工具。智能云开发环境如 Google 的 Project IDX 等工具,使得未来的开发流程更加智能化和高效。

这些变化不仅提高了开发效率和质量,还推动了整个软件工程领域的发展。

相关材料:

材料见:大模型时代, AI 辅助编程工具的技术演进

AI 辅助软件工程:AI4SE 体系设计

受限于自身企业的规模与人员结构,AI 辅助软件工程(AI4SE)的设计与实施过程会有所差异。诸如于:

  • 研发外包型企业,对于 AI 辅助研发的需求并没有特别强烈?(待进一步调研)
  • 小型研发组织,生存是主要问题,因此对于数据敏感度不高,可以采用 SaaS 方案;当团队中出现能力较强的人员时,会基于开源工具进行简单的开发。
  • 中大型研发组织,对于数据敏感度较高,因此会选择自建 AI4SE 体系,以保证数据的安全性。

结合我们在其它组织的经验,以及 ChatGPT 给我们的建议,可以得到以下的 AI4SE 体系设计流程:

  1. 初步明确 AI4SE 设计目标:确定通过 AI 实现的可落地目标,如提高开发效率和提升代码质量。
  2. 识别痛点和需求:评估当前软件工程流程中的痛点和瓶颈。
  3. 选择合适的AI技术:根据业务需求选择合适的 AI 技术,如机器学习、深度学习、自然语言处理等。
  4. 构建跨学科团队:组建包含数据科学家、AI 工程师、软件工程师和业务专家的团队,并提供AI相关培训。
  5. 开发原型与集成:开发和测试 AI 应用的原型,并将有效模型集成到现有工具链中。
  6. 逐步实施与评估:采用小规模试点逐步扩大的策略,并定期评估体系绩效,使用关键绩效指标进行衡量。
  7. 持续改进与技术更新:收集用户反馈,持续优化工具和指标,并跟踪引入最新技术和工程方法。

除此,设计适合自身公司的 AI4SE 体系是一项复杂且难度极大的工作。这一过程需要综合考虑公司的具体情况、业务需求以及现有的资源。

初步明确 AI4SE 设计目标

尽管生成式 AI 技术在软件工程领域的应用已经取得了显著进展,但在实际应用中,AI 技术的效果并不总是如人们所期望的那样。诸如于:

  • 环境适配问题。生成式 AI 可以根据一张图片生成前端代码,但由于每个企业内部使用的前端框架、组件库等不尽相同,生成的代码往往无法直接在实际项目中使用。这意味着,生成式 AI 必须考虑到不同组织的技术栈和环境需求,才能真正发挥其作用。
  • 代码质量不稳定。由于生成式 AI 的固有限制,生成的代码质量并不总是稳定或符合最佳实践标准。在实际应用中,人工审核和质量保证仍然是必不可少的。这种人机协作的方式可以弥补 AI 的不足,确保代码的可维护性和可靠性。
  • 能力限制。生成式 AI 更擅长生成新的代码,而不是修改现有的代码。这意味着在处理现有系统的维护和升级时,生成式 AI 的作用可能有限。因此,AI 需要具备与现有代码库互动的能力,才能在实际应用中提供更大的价值。
  • 上下文理解不足。生成式 AI 在生成代码时,常常无法充分理解项目的整体上下文或业务逻辑。这种上下文理解的不足,可能导致生成的代码与项目 AI 需要适当补充背景信息,才能更好地满足项目的实际需求。
  • 复杂任务处理能力有限。尽管生成式 AI 在简单的编码任务上表现出色,但在处理复杂的系统设计、架构决策或多模块集成时,其能力仍然有限。面对这些高复杂度的任务,生成式 AI 可能需要更多的人工干预与支持。
  • ……

除此,AI4SE 的设计目标还应该考虑到企业的具体情况和需求。例如,对于一家初创公司来说,提高开发效率和降低成本可能是首要目标;而对于一家传统企业来说,提升软件质量和可维护性可能更为重要。

小型研发团队:提升开发人员体验 or 改善流程规范?

对于小型研发规模的组织来说,ROI 是一个重要的考量因素 —— 与规模化提升效率相比,提升开发人员的体验是一个更合适的目标。也因此,直接采用现有的 SaaS 服务是一个更为经济的选择,结合一些 “免费” 的 AI 工具,并 提供一些内部的培训和文档,就可以实现部分 AI4SE 的关键目标。

同时,在这一阶段,我们可以通过分析现有的 AI4SE 相关工具,来了解市场上的最新技术和趋势。诸如于,我们先前分析的一些工具链示例:

环节头部工具特点典型工具
需求/项目管理AtlassianJira AI Assistant, Atlassian Intelligence构建交互式 AI 需求编辑器,提升需求编写效率。扩大生成式 AI 使用触点,提供 AI 跨工具链能力。Jira AI Assistant, Atlassian Intelligence
开发与代码协作GitHubGitHub Copilot, Copilot X, Copilot Workspace围绕代码开发、协作、构建为核心,以开发者体验作为度量体系;GitHub Copilot, Copilot X, Copilot Workspace, Dynatrace Davis
CI/CDGitHub, GitLabGitHub Action, GitLab结合代码平台,构建更符合开发者体验的开发体系
测试JetBrainsChecksum, Testim Copilot生成式 AI 测试工具,提供测试用例生成、自动化测试、测试报告等功能。Testim
文档与协作AtlassianAtlassian Rovo通过生成式 AI 解锁企业知识的工具,内建和自定义知识管理智能体。Atlassian Rovo
基础设施AWS/SysdigAmazon Q, Sysdig Sag在云平台上,关注在 AI 重新定义"安全左迁"。结合生成式 AI 与传统 AI 工具,进行云基础设施排错、问答、网络诊断等。结合云平台,提供对应 AI 辅助能力。Amazon Q, Sysdig Sag
可观测性New Relic/DynatraceNewRelic Grok, Dynatrace Davis结合传统判别式 AI 工具,无缝辅助问题定位和修复,与问题回顾。围绕新兴 AI 技术栈构建 AI 应用可观测性。NewRelic Grok
开发者工具JetBrainsAI Assistant, Grazie围绕开发人员日常活动,构建全面的 AI 辅助;在 IDE 构建精确的上下文,以获得高质量生成内容。AI Assistant, Grazie

除此,由于小团队并没有规范的流程,在关键环节上可能是缺乏的,到底是结合 AI 来引入流程,还是放弃某个流程,是一个需要考虑的问题。除此,由于过往缺少 相关的规范,AI 并不定带来很大的受益,还可能会带来额外的成本。

中大型研发团队:提升软件质量 or 降低流程成本?

对于中大型研发规模的组织来说,由于企业已经有成功的商业运营模式,与提升开发效率相比,提升软件质量和降低流程成本是更为重要的目标。毕竟,在过去的几十年间, 大量的企业在迭代自己的软件工程,从瀑布、敏捷到 DevOps,形成了一系列经典的工具和流程方法。

  • 对于质量要求高的组织来说,软件质量远比开发效率更为重要。
  • 对于流程成本高的组织来说,流程才是限制开发效率的瓶颈。
  • 对于大型系统来说,沟通成本和协作成本是更为重要的问题。
  • ……

尽管,我们会统一来看待大型组织中的 AI4SE 体系设计,但是实际上,每个组织所考虑的首要问题是不同的。我们应该根据企业的具体情况和需求,来确定我们的目标?

服务型团队:改善开发体验 or 提降低迁移成本?

除此,我们还需要考虑到团队的结构和组织文化带来的影响。诸如于,团队的拓扑结构会影响到团队的目标:

团队拓扑

对于诸如平台型团队、SaaS 企业、云服务提供商等服务型团队来说,他们的目标可能是:

  • 降低用户的迁移成本:诸如结合平台的特性,构建结合 AI 的迁移工具,以降低用户的迁移成本。
  • 提升开发人员的体验:构建辅助编码、部署等相关的 AI 工具,以提升开发人员的体验。
  • 提供基于平台的知识问答:降低用户的学习成本、知识负载。
  • ……

当然可能还存在其它类型的团队,受限于笔者的经验,这里不再一一列举。

识别痛点和需求

通常来说,目标是分为多级的,类似于 OKR 的自上而下的目标设定。在 “初步明确 AI4SE 设计目标” 中指的是由高层决策者确定的目标,而在这里, 通常是真正的痛点和需求,需要由组织的中层管理者,诸如研发效能/工程效能团队等来确定。当然了,再往下,就是由团队的一线开发人员来确定,诸如更详细的 实施细节和指标等。

基于软件生命周期分析/DevOps 流程分析

当企业构建成熟的 DevOps 流程时,AI4SE 的实施会更加顺利。下图是,Thoughtworks 在 2023 年初对 AI 辅助软件工程的流程分析,即在软件开发的不同阶段,AI 可以提供哪些辅助功能:

我们就可以探索如何在不同阶段使用 AI 工具,而在这时需要不同的角色参与到这个过程中,以确保我们设计出来的体系符合不同角色的需求。 例如:

  • 产品经理:在需求分析和项目规划阶段,AI 可以帮助自动生成需求文档,或进行需求优先级排序。
  • 开发人员:在编码和测试阶段,AI 工具可以辅助代码生成、代码审查以及自动化测试。
  • 运维人员:在部署和监控阶段,AI 能提供智能化的日志分析、自动化故障排除和性能优化建议。
  • ……

而随着我们探索的进一步深入,可以建立多阶段协同的 AI4SE 体系,如:AI 根因分析时能自动修复代码问题。

基于数据分析与识别

市面上已经有大量的关于软件工程效率和 AI 相关的数据分析报告,诸如于 JetBrains 和 GitKraken 的 2024 State of Git Collaboration 年度报告,会指出:

  • 较小的团队通常在敏捷性和满意度方面表现优于较大的团队。
  • 团队成功的关键似乎在于团队成员数量与任务管理之间的平衡。

而其中会发现团队在上下文切换、不明确的优先事项和无效会议等方面存在问题,导致浪费时间和精力,真正在编码的时间不到总工作时间的 40%。

Context Switch

除此,再加上不明确的优先事项,使开发人员不确定哪些任务需要立即关注,这些陷阱可能会创造一个充满挑战的工作环境。 为了解决这些问题,团队应实施清晰的沟通渠道,以减少上下文切换的需求,并简化会议议程,以确保每次会议都有明确的目的和清晰的结果。

"上下文切换、不明确的优先事项和那些永无止境的会议。它们感觉像是烦恼,而 GitKraken 的这份报告有数据证实它们确实是烦恼。作为开发人员和开发团队, 是时候寻找匹配我们需求的工具和工作流程,消除让我们不开心的噪音。进入状态,构建出色的软件!" —— GitKraken CEO:Matt Johnston

通过识别这些痛点并针对性地引入 AI4SE 工具和流程优化,团队可以显著提升工作效率和满意度,为构建更高质量的软件奠定基础。

选择合适的 AI 技术

在原型开发阶段,可以尝试不同的 AI 技术,如机器学习、深度学习、自然语言处理等,以确定最适合公司需求的技术。 而在实际应用中,需要考虑 AI 模型与基础设施的集成、数据安全性、模型解释性等因素。

结合内部技术栈

由于,大量的 AI 科研人员使用的是 Python 语言,已经有大量的 AI 开发框架和基础设施, 因此人们喜欢优先考虑 Python 作为 AI 开发语言。这种趋势也从科研和一些基础设施影响到了应用层。如在 2023 年,Python 生态下的 LangChain 和 LlamaIndex 是人们构建生成式 AI 的两个主要框架。

回到企业应用开发时,可能更倾向于使用 Java、C++ 或其他语言。 诸如于我们在设计 Unit Mesh 相关开源方案时,由于内部大量的基础设施是建立在 JVM 上,因此我们选择了 Kotlin 作为主要的开发语言,开发了对应的 LLM 开发框架 ChocoBuilder,以支持 AI 模型的快速构建。如今不同的语言也有不同的 LLM 开发框架,如:Spring AI 等。

在典型的向量数据库层面,没有技术栈限制的组织,可以灵活地选择新的向量数据库,如:Milvus、Qdrant 等,以支持 AI 模型的快速检索。而有技术栈限制的组织, 往往会结合过往的技术栈,如支持向量搜索的 ElasticSearch 版本,PostgreSQL + pgvector 等。

采用主流 AI 工具的技术栈

在另一方面,我们注意到,国内的AI辅助编程工具,早期大多采用与 GitHub Copilot 类似的技术栈、算法和交互方式。许多领先的AI辅助编码工具,在代码分层、 文件命名以及变量命名等方面,都展现出高度的相似性,其精细程度,宛如天工。

考虑到在这些 AI 辅助研发领域,诸多东西都是相似的,我们可以参考主流的技术栈实现与实现思路:

  • 结合 TF/IDF 或者 BM25 算法改进代码检索的效果,提高代码检索的准确性。
  • 采用 Jaccard 相似度算法,提高代码相似性检测的效果。
  • 使用 TreeSitter 或者 AST 技术,进行语法分析,以构建更好的交互体验。
  • ……

只是呢,算法、工具和技术栈等都存在学习成本,还需要结合团队的实际情况,选择合适的 AI 技术。诸如:Continue.Dev 采用 JavaScript + WASM + LanceDB 作为本地向量技术栈, 而通义灵码采用的是 RocksDB 作为本地向量技术栈。

构建跨学科团队

在构建 AI4SE 体系时,跨学科团队的协作至关重要。AI 工程师与数据工程师通常在算法设计、模型训练和数据处理方面具有专长,但他们可能不熟悉软件工程的最佳实践、 架构设计和代码维护。而软件工程师则在构建可靠、高效的软件系统方面有丰富的经验,但在 AI 模型的开发和调优方面可能缺乏深入的了解。

跨学科团队

创建一个跨学科团队,结合两者的优势,是成功实施 AI4SE 体系的关键。:

  • 互补能力:通过培训和知识共享,让团队成员了解彼此的工作领域。AI 工程师可以学习基本的软件工程原则,而软件工程师可以学习如何利用 AI 工具和模型。
  • 协作工具:使用协作工具和平台,如知识库和实时协作软件,帮助团队成员共享信息和进展。
  • 定期沟通:定期组织团队会议,确保每个成员都能了解项目的整体进展,及时解决跨学科合作中的挑战。

当然了,如果能定期与其它团队进行交流,也是非常有帮助的。诸如于我们在 Thoughtworks 的开源项目中,我们会定期与其它团队进行交流,以了解其它团队的 AI4SE 体系设计,以及其它团队的 AI4SE 体系设计的优势和不足。

相似的,构建这种跨团队的激励机制和协作,也是另外一个非常大的挑战。

软件工程是 AI4SE 的基础

笔者作为一个典型的工程师,会更倾向于认为软件工程是 AI4SE 的基础。理解软件工程的基本原则和最佳实践,是这个团队必须要具备的能力。诸如,你需要理解

  • 开发人员如何编码测试,才能设计好 AI 生成测试。
  • 团队中的人员能力差异,以设计适合不同梯队的功能需求。
  • 软件开发的编码规范与习惯,以设计出规范化的代码生成。
  • 理解如何编码,以在 IDE 的不同触点上提供 AI 功能。
  • ……

诸如此类的还有开发人员的日常工作流程、代码审查、代码合并、代码测试等是如何进行的,这些都是 AI4SE 体系设计的基础。尽管,你可以通过对开发人员进行 访谈、观察开发人员的日常工作流程等方式,来了解这些基础知识,但是,如果你自己不具备这些基础知识,那么你很难设计出一个符合实际需求的 AI 工具。

开发原型与集成

一个早期可工作的原型是整个体系的关键,它可以帮助团队快速验证可行性,并决定下一步的发展方向与资源的多少。通常来说,在当前阶段,我们可以看到诸多 企业会基于市面上开源的成熟或者半成熟的 AI4SE 工具,进行原型开发。

基于开源软件构建原型:AutoDev 示例

我们在 2023 年的早期构建了开源的 AI 辅助研发工具 AutoDev,作为国内首个开源的 AI 辅助研发方案。通过 GitHub 的 issue,我们看到了大量的企业和团队基于其进行原型开发:

  • 结合免费的 SaaS/MaaS 服务,以让自己有一个 “免费” 的 AI 编码助手。
  • 使用 Ollma 在本地运行 LLM,以探索 AutoDev 的能力。
  • 在企业内部部署 One API 服务,以试验不同的模型在实际项目中的效果。
  • 基于 AutoDev 定制,以满足特定的业务需求。
  • ……

类似的,我们也可以在企业内部以相似的方式,基于市面上的开源工具,进行原型开发。

构建适合原型开发的 SDK

我们在设计 LLM 开发框架 ChocoBuilder 时,构建了一系列帮助开发人员快速构建原型的能力, 以验证 AI 模型在实际项目中的应用效果。如下是 ChocoBuilder 构建 RAG 的示例:

@file:DependsOn("cc.unitmesh:rag-script:0.4.6")

import cc.unitmesh.rag.*

rag {
    indexing {
        val chunks = document("README.md").split()
        store.indexing(chunks)
    }

    querying {
        store.findRelevant("workflow dsl design ")
            .lowInMiddle()
            .also {
                println(it)
            }
    }
}

在这个示例中,我们使用 RAG 脚本将文档内容分块并进行索引,然后通过查询相关内容,展示了如何在开发环境中快速测试和集成 AI 功能。

逐步实施与评估

在企业中,由于多数工具团队在过往有失败的工具推广经验,所以在推广工具时,往往会采用渐进式的策略,以有效降低风险,并使团队能够逐步适应新技术。也因此, 如何设计合理的度量体系来监控和评估 AI4SE 的效果是至关重要的。

通常来说,我们会关注于以下几个方面:

  • 开发效率:评估引入 AI 工具后,编码速度是否得到了提高,例如,代码接受率、代码入库率、响应时间等。
  • 代码质量:使用静态分析工具和代码审查来衡量 AI 生成代码的质量,评估 AI 生成质量和代码可维护性。
  • 用户满意度:收集开发团队对 AI 工具的使用反馈,分析其在实际工作中的体验和效果。
  • 功能使用频次:监控不同 AI 功能的使用频次,了解团队对 AI 工具的偏好和需求。
  • 业务指标:通过业务关键绩效指标(KPI)来衡量其对整体项目进展和成功率的影响。
  • ……

需要注意的是,由于统计口径上的差异,会导致不同的度量体系下的同一个指标有不同的结果。诸如于,AI 代码入库率可能会涉及到 3、 5、10 分钟内的代码变更, 又或者是用户无操作等不同口径;代码接受率会受到语言因素影响较大,如有的模型 Python 代码接受率可能会高于 Java 代码接受率,而静态类型语言的代码接受率 远高于动态类型语言。

这些指标都需要在初步运行后,根据团队的实际情况进行调整,以确保度量体系的有效性和可靠性。

持续改进与技术更新

AI 技术在过去的一年里发展迅猛,新的 AI 工具和模型不断涌现,为软件工程带来了更多的可能性。这也是笔者构建《AI 辅助软件工程:实践与案例解析》(https://github.com/phodal/aise )这个开源项目的原因之一。

对于企业来说也是相似的,我们还需要:

  • 反馈回路:建立高效的反馈回路,收集团队对 AI 工具和模型的使用体验,及时调整和优化。
  • 技术跟踪:定期更新和引入新技术,保持体系的竞争力。关注业界最新的 AI 发展趋势,并评估其在现有体系中的适用性。
  • 培训与支持:为团队提供持续的培训,帮助他们跟上技术更新,确保团队始终具备必要的技能来使用和维护 AI4SE 体系。

此外,还应该提供以下支持:

  • 建立支持渠道:确保团队成员在遇到问题时能够及时获得帮助,可以是通过内部的交流群组、论坛或者专门的 support team。
  • 鼓励知识分享:定期组织知识分享会,鼓励团队成员分享他们的经验和学习心得。
  • 跟踪技术进展:持续关注 AI 领域的最新进展,通过内部研讨会或外部培训,让团队成员了解最新的技术动态。

现在,你还多了一个新的方式,加入这个开源项目的 issue、discussions,或者是直接在 GitHub 上提交 PR,来参与到这个项目中。

AI 辅助软件工程:AI4SE 设计原则

AI4SE(Artificial Intelligence for Software Engineering)是指将人工智能技术应用于软件工程领域,旨在通过 AI 算法和工具改进软件开发、维护、测试和管理等环节的效率与效果。AI4SE 的核心目标是通过自动化与智能化技术,降低软件开发的复杂性,提升软件质量,并加快软件工程的进程。

核心设计原则

在先前的《LLM 优先的软件架构设计原则》一节中,我们思考了适合于 LLM 应用开发的设计原则。 在结合生成式 AI 构建软件领域的实践经验和案例分析后,我们总结了以下 AI4SE 设计原则:

  • 以人为本,AI 为辅
  • 上下文智能化
  • 数据驱动的闭环反馈

以人为本,AI 为辅

AI 应被设计为提升人类生产力的工具,而非取代人类。在软件工程领域,AI 的作用是为开发者提供更多选择和更优质的决策支持。我们将 AI 辅助软件工程分为三个阶段/角色,分别是共航者(Co-Pilot)、共融者(Co-Integrator)和共促者(Co-Facilitator)。

共航者(Co-Pilot)

  • 减少重复性工作:通过自动化重复和低价值任务,如数据录入和基础分析,AI 可以释放开发者的时间和精力。
  • 辅助决策:AI 能通过数据挖掘和分析,为开发者提供有价值的洞察和建议,帮助他们在复杂环境中做出更明智的选择。
  • 实时反馈与优化:在任务执行过程中,AI 能提供即时反馈与建议,帮助用户持续优化决策与行动方案。

共融者(Co-Integrator)

  • 提高工作效率:AI 能够优化和自动化工作流程,减少人为错误,提升整体效率。例如,在制造业中,AI 可以实时监控和调整生产线,从而提高生产效率与产品质量。
  • 整合多源数据:AI 可以从多个数据源中提取信息,并进行综合分析,为用户提供全面的视角和深刻的洞察。
  • 促进跨领域协作:AI 可以连接不同领域的知识和资源,促进跨学科和跨行业的合作与创新,推动技术与社会的进步。

共促者(Co-Facilitator)

  • 增强学习与发展:AI 可以作为学习工具,帮助人类持续提升技能和知识。通过智能辅导系统,AI 可以根据学习者的进度和需求,提供个性化的学习路径与资源。
  • 组织协调:AI 能通过全面的分析与预测,帮助组织优化资源分配、进度管理与风险控制,从而提升整体运营效率。

AI 通过这三个角色,超越了简单的工具定位,成为开发者不可或缺的合作伙伴。它不仅帮助我们解决当下的挑战,更为我们赋能,引领我们迈向更加创新与高效的未来。

上下文智能化

有效的 AI 辅助研发工具,不仅仅是机械地执行简单的命令,它需要具备上下文感知能力。诸如于 SourceGraph 的文章《Why context awareness is challenging for code AI 》对些的深入探讨:

  • 人类与 AI 的上下文差异:人类开发者依赖丰富且个性化的上下文知识,而 AI 则依赖于其训练数据中的通用上下文。这种差异意味着 AI 必须学会更好地理解和适应特定的任务环境。
  • 增强 AI 的上下文感知:为了提高 AI 的有效性,应通过引入与任务相关的上下文知识来增强其能力,使其能够更接近人类开发者的思维过程。 这种上下文不仅包括代码本身,还应包括开发者的习惯和项目的历史背景。
  • 从繁琐到智能的转变:虽然理论上可以通过手动复制粘贴代码来提供上下文,但这种方法既繁琐又违背了使用 AI 助手的初衷。目标应是让 AI 自动检索并利用相关上下文,从而提供更精准且实用的输出。
  • 多层次的上下文支持:根据任务的复杂性,AI 需要获得不同层次的上下文支持,从本地文件级别到仓库级别,再到远程仓库的广泛上下文。 每个层次的上下文都有助于提高 AI 的决策能力。
  • 技术挑战与前景:目前,许多 AI 工具可以处理本地文件的上下文,但当涉及到整个仓库,尤其是远程仓库的上下文时,仍然面临技术挑战。 这些挑战包括如何有效检索、分析和应用大量的代码和文档信息。

同时,AI工具应提供灵活的控制选项,以适应不同开发者的需求和工作方式。AI通过提供多种推荐选项,协助开发者依据个人偏好和习惯进行选择,进而提升工作效率。

通过减少对 AI 操作的硬性控制,并增强其上下文感知能力,可以构建更加智能且高效的开发环境。这使得AI真正成为开发者的得力助手。

数据驱动的闭环反馈

成功的 AI4SE 不仅依赖于数据的驱动,还必须优先考虑开发者体验。通过构建闭环反馈机制,AI 工具能够不断适应和改进,以满足开发者的实际需求,实现高效、智能的开发支持。

数据驱动与动态反馈

  • 数据收集与分析:AI 系统的性能依赖于高质量的数据。为了确保工具的有效性,AI 应自动化收集、分析并维护数据,为开发者提供有深度的洞察。这些数据可以包括代码库的变化、开发者的使用习惯以及项目进度等。
  • 持续学习与优化:AI 系统应具备持续学习和适应能力,能够根据实时更新的数据不断调整和优化其表现。这种自我优化的过程使 AI 工具能够随着项目的发展和用户需求的变化不断进步。
  • 透明的决策机制:AI 工具应向开发者清晰展示其决策依据,使用户能够理解 AI 的逻辑和推理过程。这种透明性不仅增加了工具的可信度,也帮助开发者在使用过程中更好地掌控和调整 AI 的输出。

围绕开发者体验构建闭环反馈

  • 实时反馈机制:AI 工具应提供实时的反馈,帮助开发者在编写代码、调试和测试的过程中获得及时的支持。这种即时反馈能够让开发者迅速发现和解决问题,提升整体工作效率。
  • 用户体验优化:基于用户的实时反馈,AI 工具应不断优化其界面和功能,以提高易用性和用户满意度。通过迭代改进,工具可以更加贴合开发者的实际需求。
  • 个性化建议与调整:AI 工具应根据开发者的工作习惯和偏好,提供个性化的功能和建议。同时,工具应具备学习能力,能够根据反馈不断调整其行为和建议,确保其适应性和精准度。
  • 无缝集成与协作:AI 工具应无缝集成到开发者的工作流程中,减少上下文切换,提升团队协作的效率。通过这种集成,AI 不仅能为个体开发者提供支持,还能促进团队间的知识共享与合作。

通过数据驱动的决策和闭环反馈机制,AI4SE 工具能够不断适应和进化,为开发者提供更加智能、精准和高效的支持,最终助力他们在复杂的开发环境中实现卓越的成果。

AI 辅助软件工程:软件生命周期驱动的 AI4SE

生成式 AI 并非银弹。

当我们谈及 AI 辅助软件工程时,我们期望的是 AI 能在改善即有流程的现状,同时提供更多的可能性,诸如于:

  1. 自动代码修复: 利用 AI 技术分析代码并提出修复建议,帮助开发者更快速地解决问题。
  2. 智能代码补全:类似于 GitHub Copilot 和 TabNine,根据上下文预测开发者可能编写的下一行代码,大大提高编码效率。
  3. 代码重构: 识别出需要重构的代码片段,并提供重构建议,并应用代码重构。
  4. 单元测试生成: 自动生成单元测试,帮助开发者确保代码的正确性和可靠性。
  5. 代码合并和冲突解决:帮助自动化代码合并过程,并智能解决合并冲突。
  6. 性能优化建议:学习历史数据和性能模式,帮助开发者识别出影响性能的代码部分,并提供具体的优化方案。
  7. 安全漏洞检测: 检测代码中的安全漏洞,并提供修复建议。
  8. 代码审查助手: 自动检测代码中的问题并提出改进建议,提供详细的审查报告,帮助审查人员更高效地进行代码评审。
  9. ……

但是,并非所有的环节都需要结合 AI、适合 AI,有些环节反而会因为 AI 的引入而增加复杂性,降低效率。

AI 要解决什么问题?软件工程面临的挑战

我们总期待生成式 AI 能解决一部分软件开发中的问题,但是限制我们软件交付速度的往往不是技术,而是人。人与人之间的协作、人对需求的理解、人对已有代码的理解等等。 理想情况下,只有人被取代了,那么问题才会消失。可是,AI 并不能代替你去坐牢,所以最后还是需要人来做决策。

生命周期内的挑战

完全按照某一特定的开发流程来开发软件是不现实的。在组织中,我们总是允许每个团队根据自己的现状,来适当地改造软件开发流程。也因此,每个团队所面临的 挑战也是不同的。诸如于,我们典型的分析方式是根据软件生命周期的不同阶段来审视和分析。

如下是由生成式 AI 生成的软件生命周期的挑战:

  1. 需求分析阶段
    • 需求变更和管理:需求往往会在项目生命周期中发生变化,不良的变更管理可能导致项目延迟和成本增加。
    • 需求不完整或不清晰:如果需求定义不清晰或不完整,可能会导致后续阶段的问题,如设计和开发时的误解或错误。
  2. 设计阶段
    • 架构设计挑战:设计阶段需要考虑系统架构、模块化、性能和可扩展性,这些方面的决策会对整个项目的成功产生深远影响。
    • 设计与需求的一致性:确保设计方案与需求规格的一致性,以及如何适应可能的变更。
  3. 开发阶段
    • 技术选型和工具挑战:选择适合项目需求的技术栈和工具集合是一个重要的决策,可能会影响到开发进度和产品质量。
    • 团队协作和沟通:大型项目中,多个开发者的协作和沟通是关键,特别是在分布式团队或跨时区工作的情况下。
  4. 测试阶段
    • 全面性测试覆盖:确保测试用例覆盖所有功能和边界情况,以及如何处理复杂系统的集成测试。
    • 自动化测试和持续集成:实现自动化测试并结合持续集成可以显著提高软件质量和开发效率。
  5. 部署阶段
    • 部署流程自动化:设计和实施可靠的部署流程,包括配置管理、版本控制和部署自动化,以降低部署错误的风险。
    • 环境一致性和兼容性:确保在不同环境(开发、测试、生产)中软件的一致性和兼容性,尤其是涉及复杂的分布式系统时更为关键。
  6. 维护阶段
    • 问题追踪和修复:确保能够及时发现和解决生产环境中出现的问题,需要有效的问题追踪和处理流程。
    • 版本管理和更新:管理和维护软件的不同版本,包括安全更新和功能更新,以及如何进行版本回退和紧急修复。

总的来说,这些挑战是非常常见且具体的,放到一个大型组织中,上述问题几乎也是非常相似的。当你进行详细的分析之后,你会发现,AI 只能解决一部分问题, 并且经典的软件工程方法和工具也能解决一部分问题,当然了最后所有的问题都是人的问题。

其它挑战

除此,我们还会遇到一些外部的挑战,这些挑战可能会对软件开发团队的工作产生影响,包括但不限于:

  1. 项目管理和进度控制
    • 资源管理与分配:确保项目所需资源(人力、技术、资金)的有效管理和分配,以支持软件开发的不同阶段。
    • 风险管理:识别、评估和管理项目中可能出现的风险,包括技术风险、市场风险和组织风险,以最小化其对项目目标的负面影响。
  2. 质量保证和标准遵循
    • 质量管理系统:实施和维护适当的质量管理系统,以确保软件质量达到用户期望和行业标准。
    • 安全性和合规性:确保软件在设计、开发和部署过程中符合安全标准和法规要求,特别是涉及用户数据或敏感信息的应用程序。
  3. 项目间协作
    • 跨团队协作:确保不同团队之间的有效沟通和协作,特别是在大型和分布式团队的情况下,以确保整体项目目标的一致性和实现。
  4. 遗留系统和技术债务
    • 云原生和微服务架构:这些技术推动了软件开发的灵活性和可扩展性,但也带来了新的挑战,如服务治理、服务发现和跨服务的数据一致性。
    • DevOps 实践:自动化部署、持续集成和持续交付(CI/CD)的实施,以及开发团队与运维团队之间协作的增强,要求文化和工具的整合。
    • 容器化技术(如Docker):管理和部署容器化应用程序的复杂性,以及与传统部署方式的集成和过渡。

与上述的软件生命周期挑战相比,这些外部挑战更多地涉及到组织和行业层面的问题,更难通过 AI 来解决。

应用 AI 之前:经典工具可行吗?

现阶段,我们(包含笔者在内)将 AI 当成一把锤子,看到的问题都是钉子(锤子效应),尝试用 AI 来解决所有问题。但是,AI 并不是银弹,也并不是万能的。

而过去的几十年里,在软件工程领域已经积累了足够的经验和知识,形成了一系列经典的工具和方法,用于解决软件开发和维护过程中的各种问题。 这些工具和方法包括代码质量检查、架构设计、自动化测试、安全测试等,已经在实践中得到了广泛应用。这些工具和方法包括但不限于:

  • SonarQube:用于代码质量检查和静态代码分析的工具,可以帮助开发团队发现和修复潜在的代码问题。
  • ArchGuard:用于架构设计和评估的工具,可以帮助团队设计和优化系统架构。
  • ArchUnit:用于架构单元测试的工具,可以帮助团队验证架构设计的一致性和正确性。
  • EvoSuite:用于自动生成测试用例的工具,可以帮助团队提高测试覆盖率和质量。
  • Checkstyle:代码风格和质量检查工具,可配置规则来确保代码符合指定的编码标准。
  • FindBugs:用于Java代码的静态分析工具,帮助开发者发现常见的编程错误和潜在的安全漏洞。
  • OWASP Zap:开源的安全测试工具,用于查找Web应用程序中的安全漏洞和漏洞利用。
  • ……

除此,还有诸如 SAST (Static Application Security Testing) 和 DAST (Dynamic Application Security Testing) :这两种测试方法结合了不同的工具和技术,分别用于静态和动态地评估应用程序的安全性。

  • Facebook's Aroma:一个代码推荐系统,可以从大型代码库中提取代码模式,并为开发者提供优化建议。
  • SourceGraph:一个代码搜索和导航工具,可以帮助开发者快速定位和理解代码库中的代码片段。
  • ……

当然了诸如此类的工具和方法,也需要大量的开发成本。

现在,考虑一下 AI 要解决什么问题?

现在,我们再考虑一下 AI 能不能解决问题?以及 AI 要解决什么问题?针对于不同的场景,方案是不同的。我们分析了市面上的主要 AI 工具,发现 AI 工具 的两种主要实现策略:

  • 增强现有工具。诸如结合 AI 通过分析大量的代码库和历史数据,生成更智能和精确的代码检查规则,帮助开发团队及时发现潜在的错误和漏洞。
  • AI 原生的软件工程工具。市面上的工具如 GitHub Copilot、Testim.io、Snyk(DeepCode)等,都是基于 AI 技术构建的新型软件工程工具,可以帮助开发团队提高生产力和质量。

由于生成式 AI 存在的幻觉问题,我们更倾向于增强现有工具,而不是完全替代。

实现策略:增强现有工具

在代码质量等场景,已经有大量的团队尝试直接将所有的上下文发给 AI,然后交由 AI 来处理。这种方式不仅是低效的,而且也会导致 AI 无法真正发挥作用。 在这些场景中,类似的方案应该是:

  • 生成检查规则:像 SonarQube 和 Checkstyle 这样的工具可以利用AI技术生成更智能和精确的代码检查规则。AI 能识别出更有效的代码质量问题,并提出更具针对性的检查建议,帮助开发团队及时发现潜在的错误和漏洞。
  • 误判处理:在静态代码分析中,经典工具有时会误判某些代码片段或模式。AI 可以识别这些误判,并提供更准确的判断或建议,帮助开发团队减少误报,节省审查和修复的时间。
  • 辅助边界测试用例生成:工具如 EvoSuite 用于自动生成测试用例,结合AI技术可以更快速地生成全面且有效的测试覆盖。AI能够分析代码逻辑和历史的错误模式,生成更具预测性和全面性的测试用例,帮助团队提高软件质量和稳定性。
  • 辅助架构治理边界:像 ArchGuard 和 ArchUnit 这样的工具在架构设计和测试中发挥重要作用。AI 通过分析大量系统使用数据和性能指标,提供优化架构的建议和模型,帮助团队设计更高效、可靠和可扩展的系统架构。
  • ……

在诸如于 CodeQL 和 SonarQube,结合领域的 AI 模型或者 RAG,我们可以生成对应的代码检查规则,而不是人工编写。随后,再结合 AI 来帮助人们处理过程中的误差问题。

实现策略:AI 原生的软件工程工具

在特定的小流程中,AI 原生的软件工程工具可能会更加适用。这些工具通常是基于 AI 技术构建的新型软件工程工具,可以帮助开发团队提高生产力和质量。诸如于:

  • GitHub Copilot:一个基于 OpenAI Codex 的代码补全工具,可以根据上下文自动生成代码片段,提高开发效率。
  • Testim.io:基于AI的端到端测试自动化工具,帮助开发团队快速创建、执行和维护测试用例。
  • Snyk(DeepCode):一个AI驱动的代码审查工具,通过机器学习算法检测代码中的错误、漏洞和潜在问题,并提供修复建议。
  • ……

它们的特别是针对于特定的场景,如测试、代码、质量,构建专用的模型和工具,以真正释放 AI 的潜力。

AI 辅助软件工程案例分析:Tabnine DevOps 驱动的 AI4SE

本节将探讨 Tabnine 如何巧妙地将生成式 AI 融入 SDLC,通过优化各个开发环节,从而提升开发团队的生产效率及其协作水平。

PS:尽管 Tabnine 的一些观点和产品示例是虚构的,但是他们的技术博客和产品展示给我们提供了一些有趣的想法,可以帮助我们更好地理解 AI4SE 的未来。

AI 与 SDLC 的深度融合

CI to AI

  • 效率和生产力:。AI 显著减少了开发人员的任务时间,例如,代码重构时间减少 30%,代码生成时间减少 45%,文档编写时间减少 50%;它将高复杂度任务的完成率提高了 30%。
  • 开发人员满意度:。AI 工具提高了开发人员专注于有意义工作的能力,使满意度从45%提高到88%。
  • 采用和集成:。AI 无缝集成到主要 IDE 中,并支持多种编程语言和框架;可定制模型可以在特定数据上进行训练,以提高输出质量。

1. 规划阶段的AI助力

在SDLC的规划阶段,开发人员通常需要花费大量时间查找和理解项目的现有代码。Tabnine 通过分析本地和全球代码库,提供即时的代码建议和解决方案, 使开发人员能够迅速找到所需的信息,从而减少无效的时间消耗,并帮助团队更好地制定开发计划。

2. 创建阶段的代码生成

Tabnine的AI工具在代码创建过程中尤为强大。通过智能代码补全和生成功能,开发人员可以依赖Tabnine在低复杂度任务(如创建简单类)和高复杂度任务(如解析数据结构)中提供的支持。 这样的自动化不仅加快了开发速度,还减少了错误的发生概率。

3. 测试阶段的自动化生成

AI在测试阶段的应用也极大地提升了效率。Tabnine能够自动生成单元测试,确保代码的高覆盖率,同时减少了开发人员手动编写测试用例的负担。 它还支持生成符合现有测试框架的断言,从而简化了测试过程。

4. 修复错误与实时反馈

在错误修复阶段,Tabnine的AI提供实时的错误检测和修复建议,帮助开发人员迅速定位并解决问题。这种基于上下文的个性化建议, 可以显著减少调试时间,并提高代码的可靠性。

5. 文档编写的自动化

文档编写是开发过程中常被忽视但至关重要的部分。Tabnine通过生成全面的代码文档,包括API指南、注释和内联文档,不仅提高了代码的可读性, 还帮助新开发人员更快地理解和维护代码。

6. 代码维护的智能支持

在维护阶段,Tabnine通过提供代码的全局视图和上下文相关的建议,简化了代码的重构和优化。它能够帮助团队成员理解复杂的代码结构, 从而加速新成员的入职流程,并确保代码的长期可维护性。

Tabnine + SDLC 智能体

Tabnine Connection

Onboarding Agent:加速新成员入职

Onboarding Agent 是 Tabnine 推出的一项新功能, 专为开发人员在新项目中快速适应而设计。它通过提供项目结构、可运行脚本和依赖关系的简明总结,极大地简化了新开发人员的入职过程。

Onboarding Agent

Onboarding Agent不仅提升了团队的整体效率,还增强了开发人员的自主性,使他们能够更快地融入团队并开始有效工作。

  1. 集成与可用性

    • 作为 Tabnine Chat 的内置命令,无缝集成。
    • 对所有 Tabnine SaaS 用户和支持 Tabnine AI 的 IDE 兼容。
  2. 操作简便

    • 可通过简单命令 (/onboarding) 或在新对话开始时自动触发。
    • 提供项目结构、可运行脚本、依赖关系等的简明总结。
  3. 互动和个性化

    • 不仅提供信息摘要,还作为一个导游,为用户提供定制的后续问题建议。
    • 让开发人员可以根据自己的需要深入探索项目的特定部分。

对开发人员的益处:

  • 提高效率:加快了新项目的熟悉过程,节省时间。
  • 增强自主性:使开发人员能够独立地了解和操作项目。
  • 快速上手:帮助他们更快地成为项目团队的有效成员。

对组织的益处:

  • 降低成本:减少了资深团队成员辅助新人的时间成本。
  • 优化工作流程:简化了新成员加入或项目切换带来的工作中断。
  • 知识分享:促进组织内部的效率和知识共享文化。

Onboarding Agent 代表了开发工具领域的重要进展,旨在提升开发效率,加速项目启动时间,为组织带来更高的创新能力和竞争力。

Jira-to-Code:从需求到代码的智能转化

Tabnine 与 Atlassian Jira 的集成 展示了AI在将需求直接转化为代码方面的巨大潜力。通过Tabnine的Jira-to-code智能体,开发团队可以从Jira任务中自动生成功能完备的应用程序。尽管这一功能仍处于早期阶段,但它展示了AI如何通过简洁、个性化和反思性的方法,大幅度提升软件开发的效率。

最近公布的智能体,如SWE-Agent、gpt-engineer、Devika和Devin展示了巨大的潜力,并展示了AI智能体在软件开发生命周期中不断增加的潜力。 这些智能体配备了类似于开发人员可用工具的广泛工具包,以完成他们的任务。为了在企业环境中使这些智能体成为高效的现实,我们认为智能体应具备以下特性:

  • 简洁性:与智能体的交流必须简洁明了。这不仅适用于向智能体提供输入,也适用于消耗其输出。软件开发的重要部分是从通常不充分定义的定义中发现所需的行为。智能体的效果很大程度上取决于能够快速迭代任务,并以紧凑的输入和输出进行交互。
  • 个性化和增量化:智能体必须意识到当前代码库、组织的最佳实践、文档和它所协助的人类开发者的风格和偏好。一个生成与当前代码库不一致代码的智能体,可能会限制其适用性,而不是重新利用组件。
  • 可靠性:人类必须信任智能体提供的输出。审查智能体生成的成千上万行代码以发现微妙的错误,可能会限制委托任务给智能体的价值。
  • 探索性:一个有效的智能体必须能够在需要时向人类探询额外的上下文和指令。人 <-> AI 对话的效果对智能体在实际生活中的成功至关重要。
  • 自我意识(反思性):智能体必须能够意识到当其完成一个任务并得到不满意的结果时。一个有效的智能体应该能够向人类反馈如何完成任务,以指导其改进过程。

Tabnine实现AI智能体的方法

  • 自然语言交互:通过Tabnine Chat提供企业级、以代码为中心的聊天应用程序,允许开发者使用自然语言与AI模型交互,关联Jira工单并手动修改生成的代码。
  • 上下文感知:向智能体提供Tabnine关于项目的丰富信息,并支持IDE操作工具,检索信息来自向量内存和语义内存。
  • 沙盒执行环境:允许智能体执行生成的代码并检查其符合测试用例,未来计划通过集成额外工具改进。
  • 提出澄清问题和后续问题:智能体会在任务执行中主动向人类开发者提出澄清和后续问题,以应对任务的现实复杂性。
  • 智能体反思机制:智能体会反思其工作,并可能对计划进行内部调整或提出更多问题,保持“人在循环”的反馈机制。

Tabnine Context aware

与 Bitbucket 的全面集成

Tabnine与Atlassian Bitbucket 的集成进一步展示了AI在增强开发运维(DevOps)流程中的作用。通过与Bitbucket的深度连接,Tabnine能够为整个团队提供个性化的代码建议,并帮助团队共享代码上下文,提升协作效率。此外,Tabnine还支持对AI模型进行定制,以优化在特定代码库中的表现,为开发团队提供更精准的支持。

从 DevOps 和 AI 的角度来看, Tabnine 与 Atlassian 产品的集成展示了如何利用人工智能增强开发运维(DevOps)流程的效率和质量。以下是一些关键点的总结:

  1. 全面的代码感知和个性化建议:通过与 Bitbucket 和其他 Git 仓库的集成,能够在开发者 IDE 中提供高度个性化的代码完成建议。这不仅仅是静态的代码补全,还包括变量类型、注释、已打开文件和项目的上下文信息,从而显著提升了开发者的工作效率和代码质量。
  2. 全局代码感知和团队协作:通过与 Bitbucket 的全局连接, Tabnine 扩展了其能力,使得整个工程团队能够共享和利用更丰富的代码上下文。这对于大型企业和跨部门协作的团队尤为重要,可以加强对代码库的理解和重用,从而提升整体的开发效率和协作水平。
  3. AI 模型定制和性能优化: Tabnine 通过定制 AI 模型,利用 Bitbucket 中存储的代码库进行优化,特别是针对不常见的编程语言或框架。这种个性化和优化能力提高了 AI 在软件开发过程中的表现,为开发团队提供更精准和高质量的代码生成和支持。
  4. 提升团队生产力的工具和平台支持: Atlassian 和 Tabnine 的集成不仅仅是工具级别的整合,更是为工程团队提供了全方位的工具和平台支持,帮助团队在 DevOps 实践中更有效地运用人工智能技术,从而加速交付周期、提高软件质量和团队的整体生产力。

综上所述, Tabnine 与 Atlassian 产品的结合展示了如何从 DevOps 和人工智能的融合中获得多方面的利益,为软件开发团队提供了强大的工具和平台支持,推动团队在敏捷开发和持续交付中取得更大的成功。

其它

软件开发中AI的未来:

  • AI将全面了解组织的整个工作区,导致全面的测试覆盖率和文档编写。
  • 它将显著减少代码维护所花的时间,使团队能够专注于创新。
  • 像Tabnine这样的AI工具提供安全、可定制且上下文相关的解决方案,满足企业需求,确保知识产权的控制和法律标准的合规。

通过解决这些关键领域,AI帮助软件开发团队克服了高工作量、复杂需求、技术债务和人才保留等挑战,最终提高了SDLC的整体效率和效果。

相关文章

AI 辅助软件工程:Google 开发者活动驱动的 AI 赋能

DIDACT (Dynamic Integrated Developer ACTivity) 是一种用于训练大规模机器学习(ML)模型的软件开发方法。与传统只使用完成代码的方式不同,DIDACT 创新的地方在于,它使用软件开发过程本身作为模型的训练数据来源。这意味着模型不仅能看到开发者在工作时所见的上下文,还能学习他们所采取的行动, 从而更好地理解软件开发的动态过程,并与开发者的实际工作方式对齐。

Google DIIDACT 框架:动态集成开发人员活动

Google 在内部探索了LLM for Dev Activity 方式, 以提升开发人员效率:

DIDACT

DIIDACT 框架:Smart Paste

智能粘贴是谷歌开发的一种内部工具,旨在通过自动调整粘贴代码来优化编码工作流程。这个工具利用生成式人工智能来创建上下文感知的修改,从而提高代码开发的效率。以下是其主要特点和优势的概述:

  1. 自动化的粘贴后调整:智能粘贴分析周围的代码环境,并对粘贴的代码进行必要的修改,比如添加缺失的语法、重命名变量或更改类型。这减少了粘贴代码后手动调整的工作量。
  2. 用户行为洞察:谷歌的单一代码库分析显示,大约有25%的粘贴操作会立即被修改,这可能会打断编码流程。智能粘贴通过预先进行这些常见调整,试图最小化这种中断。
  3. 生成式人工智能集成:该工具利用先进的人工智能模型(如DIDACT),预测并实现必要的变更,确保粘贴的代码与现有代码库平滑集成。
  4. 高采纳率和性能:在大约40,000名工程师的研究中,智能粘贴被使用于所有粘贴操作的6.9%,其中42.5%的建议被接受。这表明工作流效率有显著提升。
  5. 训练和校准:该模型使用谷歌单一代码库中的粘贴后编辑数据进行训练,包括不需要进行编辑的情况。这个全面的数据集帮助模型学习何时建议变更以及何时保持代码原样。
  6. 用户体验设计:该工具旨在以用户友好的方式提供高置信度的修改建议。建议会以视觉提示显示,并在特定时间内自动丢弃,以避免打断用户的工作流程。
  7. 内联差异预览:为了保持用户控制并清晰显示建议的变更,使用内联差异预览。这在编辑器中直接突出显示插入和删除的片段,使用户可以通过简单的快捷键接受建议。
  8. 未来增强计划:计划包括探索模型在复制粘贴交互之外的能力,并重新审视针对小而高置信度变更的自动应用模式。

智能粘贴代表了人工智能辅助编码工具的重大进步,减少了代码集成所需的手动工作,并提高了开发人员的整体生产力。

DIIDACT 框架:Code Review

代码更改审查是规模化软件开发过程中的关键部分,占据了代码作者和代码审查者大量的时间。在这个过程中,审查者检查提议的代码,并通过用自然语言撰写的评论向作者提出代码更改请求。

DIIDACT 框架:AutoCommenter

Paper:AI-Assisted Assessment of Coding Practices in Modern Code Review

现代代码审查(Sadowski等人,2018年;Rigby和Bird,2013年)(与整体代码审查(Fagan,1976年)相比)多年来在开源和工业环境中有机地发展壮大。已经形成了一组常见的同行评审标准(Rigby和Bird,2013年;Rigby等,2012年;Bacchelli和Bird,2013年),其中包括编码最佳实践。许多公司、项目甚至编程语言都正式定义了这些标准,以" 样式指南"的形式(goo,2024;lin,2024;pyt,2024;rus,2024),通常涵盖以下方面:

  • 格式化:行限制、空格和缩进的使用、括号和大括号的放置等;
  • 命名:大写、简洁、描述性等;
  • 文档:文件级、函数级和其他注释的预期放置和内容;
  • 语言特性:在不同(代码)上下文中使用特定语言特性;
  • 代码习惯:使用代码习惯来提高代码清晰度、模块化和可维护性。

开发人员通常对现代代码审查流程报告高度满意(Sadowski等人,2018年;Winters等人,2020年)。其中一个主要好处是对于不熟悉代码库、特定语言特性或常见代码习惯的代码作者来说,这是一个学习经验。在审查过程中,专家开发人员教育代码作者使用最佳实践,同时审查(并学习)代码贡献及其影响。 静态分析工具如linters(Johnson,1977年)可以自动验证代码是否符合某些最佳实践(例如格式化规则),有些工具甚至可以自动修复违规。然而,细致的指导方针或带有例外的指导方针在整体上很难完全自动验证(例如命名约定和对旧代码中合理偏差的正当性),有些指导方针根本无法通过精确规则捕捉(例如代码注释的清晰性和具体性),而是依赖于人类判断和集体开发者知识。因此,一般期望人类审阅员检查代码变更是否违反最佳实践。 代码审查过程的最大成本是所需的时间,尤其是来自专家开发人员的时间。即使有了显著的自动化措施,并尽可能保持流程轻量化,开发人员每天仍然可以轻松花费数小时进行此任务(Sadowski等人,2018年)。 机器学习的最新进展,特别是大型语言模型(LLMs)的能力,表明LLMs适合于代码审查自动化(例如(Tufano等人,2024年,2022年;Hong等人,2022年;Li等人,2022b,a;Thongtanunam等人,2022年))。然而,在规模化部署端到端系统的软件工程挑战仍未被探索。同样,缺乏对这些系统整体效力和用户接受度的外部评估。

本文探讨了部分自动化代码审查流程的可能性,特别是检测最佳实践违规,从而为代码作者提供及时反馈,使审阅员能够专注于整体功能。具体而言,本文报告了我们在Google工业环境中开发、部署和评估AutoCommenter——一种自动化代码审查助手的经验,目前每天由数万名开发人员使用。

DIIDACT 框架:Build Repair

我们在集成开发环境中展示了修复,并对这一功能进行了控制实验。这个实验显示,在多个生产力衡量指标上都取得了统计上显著的增益,包括代码更改数量增加了 2%。 这些增益不仅仅是为了它们自身的好处,而且通过自动化消除了开发者的重复劳动,为他们提供更多时间进行创造性问题解决。这通过消除障碍促进了专注, 从而让开发者能够更长时间保持他们的工作流状态。实际上,我们现在观察到,在一个月内遇到构建中断的用户中,约有34%最终采纳了这种由 ML 建议的修复方案。

Google Buildfix

为了评估通过我们的修复引入不正确甚至危险代码的风险,我们检查了回顾性的安全性和可靠性相关指标,包括:

  • 变更列表回滚率:生产中的问题通常通过回滚引入错误的变更列表来解决。
  • 新的检测工具失败率:谷歌运行的检测工具可以检测和标记单元测试和模糊测试中的内存损坏或泄漏问题;例如AddressSanitizer、MemorySanitizer和GWP-Asan。

我们在使用构建修复的变更列表和未使用的变更列表之间监测了这些指标,发现没有可检测的差异。

DIIDACT 框架:代码迁移

多年来,谷歌一直使用专门的基础设施来执行复杂的代码迁移。该基础设施使用静态分析和如 KytheCode Search 等工具来发现需要更改的位置及其依赖关系。然后使用如 ClangMR (Clang’s refactoring engine)等工具进行更改。

我们将迁移过程概念性地分为三个阶段:

  • 确定需要修改的代码库位置
  • 编辑生成和验证
  • 更改审查和发布

虽然这些阶段中的每一个都受益于 AI,我们主要关注第 2 阶段。

为了生成和验证代码更改,我们利用了在谷歌内部代码和数据上微调过的 Gemini 模型版本。

每次迁移需要以下输入:

  • 一组文件和预期更改的位置:路径 + 文件中的行号
  • 一到两个描述更改的提示
  • [可选] 少量示例,以确定文件是否确实需要迁移

多阶段代码迁移过程的示例执行。

用户提供的文件位置通过预先存在的静态工具和人工输入的组合进行收集。我们的迁移工具包会自动扩展这组文件,添加其他相关文件,包括:测试文件、接口文件和其他依赖项。 这一步骤尚未由 AI 驱动,但使用了符号交叉引用信息。

在许多情况下,用户提供的迁移文件集并不完美。由于过滤输入列表可能很繁琐,一些文件可能已经部分或完全迁移。因此,为了避免冗余更改或在编辑生成过程中混淆模型, 我们提供了少量示例,并要求模型预测文件是否需要迁移。

编辑生成和验证步骤是我们发现自动系统最有益的地方。我们的模型在谷歌的单体代码库和流程数据上按照 DIDACT 方法进行了训练。在推理时, 我们用自然语言指令以及模型的一般指令对每一行预计需要更改的地方进行标注。在每次模型查询中,输入上下文可以包含一个或多个相关文件。

模型然后预测文件之间的差异(diff),并且可以更改相关部分,以确保最终代码正确。

其它

相关文章:

AI 辅助软件工程:GitHub 的 AI 平台工程赋能开发者

GitHub 的案例简单来说:围绕代码的开发、协作、构建为核心,以开发者体验作为度量体系

引自官方的定义 GitHub AI 驱动的开发者平台

辅助编码:GitHub + GitHub Copilot

顶级发现显示,GitHub Copilot 有助于开发人员更快地编写代码,完成高达 46% 的代码,并使开发人员在工作中感到更加满足。

  • GitHub Copilot 数据 表明:开发人员需要差不多 3 个月才能达到的代码接受率基线水平(30%)
  • 经验少的开发者更能受益

85% 的开发者在使用 GitHub Copilot 和 GitHub Copilot Chat 编写代码时,对代码质量更有信心。

Research: Quantifying GitHub Copilot’s impact on code quality

AI 增强的安全左移

Images

  • 自动修复(autofix)静态代码问题 (结合 CodeQL 静态代码分析)
  • 密码扫描检测泄露的密码
  • 生成自定义模式 - 正则表达式

相关文章:

CodeQL 静态代码分析

Dependabot 自动化依赖更新

AI 辅助研发决策框架

A developer’s second brain: Reducing complexity through partnership with AI

  • 发现 1:认知负担确实存在,开发人员通过两种方式体验它。(太乏味了和这伤害了我的大脑")
  • 发现 2:开发者渴望 AI 协助完成复杂任务,但我们必须把握好界限
  • 发现 3:复杂任务由四个部分组成:理解(建构感知)、决策、行动计划、执行
  • 发现 4:开发者对于在理解和制定行动计划方面,接受 AI 的协助。
  • 发现 5:开发者对 AI 在决策或执行方面的自主性持谨慎态度。

Social Integration of Artificial Intelligence: Functions, Automation Allocation Logic and Human-Autonomy Trust

形态框架:

  1. 建构感知。收集和综合形成任务背景的所有相关信息。
  2. 制定行动。定义执行任务的具体步骤和步骤的顺序。
  3. 制定决策。提出应该针对这个任务采取的措施。
  4. 实现任务。执行按照定义的顺序进行的步骤。

Copilot AutoFix

Found means fixed: Secure code more than three times faster with Copilot Autofix

Copilot Autofix 是 GitHub Advanced Security (GHAS) 中一项新功能,利用 AI 技术帮助开发者更快地修复代码漏洞。它可以在开发者的拉取请求中自动生成修复方案 ,预防新漏洞进入生产环境,还可以处理现有代码中的漏洞,减轻安全债务。

主要特点包括:

  • 自动修复:在检测到漏洞后,自动生成修复建议,开发者可以选择编辑、提交或忽略这些修复。
  • 提升效率:根据公开测试数据,使用 Copilot Autofix 修复漏洞的速度显著快于手动修复。
  • 简化安全流程:它帮助开发者,即使他们不是安全专家,也能轻松理解和修复安全问题。
  • 保护开源项目:GitHub 计划在 2024 年 9 月向所有开源项目免费提供该功能。

总的来说,Copilot Autofix 通过 AI 技术简化并加速了漏洞修复过程,帮助开发者更轻松地实现安全目标。

根据 2024 年 5 月至 7 月的公开测试版客户数据,Copilot Autofix 已经显著缩短了从漏洞检测到成功修复的时间:

  • 3 倍更快。开发者使用 Copilot Autofix 自动提交拉取请求中的修复方案的中位时间为 28 分钟,而手动解决同样的警报需要 1.5 小时。
  • 7 倍更快。跨站脚本漏洞:22 分钟,而手动修复则接近三小时。
  • 12 倍更快。SQL 注入漏洞:18 分钟,而手动修复则需要 3.7 小时。

度量框架 Space

满意度和幸福感效率活动沟通和协作效率和流程
个体- 开发者满意度- 代码检视速度- 检视速度完成数量- 代码检视评分(质量或思考深度)- 代码检视时长
- 留存- 编码时长- PR 合并次数- 生产力感知
- 分配的代码检视满意度- # 代码提交次数- 会议质量- 不受打扰
- 代码审查的- 代码行数- 知识分享,可发现性(文档质量)
团队- 开发者满意度- 代码检视速度- # 完成的用户故事/需求点数- PR 合并次数- 代码检视时长
- 留存- 交付的用户故事/需求点数- 会议质量- 交接时长
系统- 平台工程的满意度(如 CI、CD 流水线等)- 代码检视速度- 部署频率- 知识分享,可发现性(文档质量)- 代码检视时长
- 代码检视接受率- 系统中的速度/流动
- 平台用户满意度
- 可靠性(正常运行时间)

AI 辅助软件工程:Gitlab 赋能开发者的 AI4SE

GitLab Duo 是团队开发的一套AI驱动功能。它革新了我们的内部工程工作流程,极大提升了开发效率。作为狗粮政策和透明度的坚定拥护者, 我们愿意展示团队如何运用AI技术。这包括GitLab Duo的代码建议和聊天功能,它们每天帮助我们简化开发流程,减少手动操作,从而提高生产力。读者将了解到, 无论是技术密集型的工程团队,还是技术要求较低的团队(例如技术写作和产品管理),都从中获得了显著的好处。

GitLab Duo 内部使用案例

我们的团队已将 GitLab Duo 的众多功能整合到日常工作中。以下是 GitLab Duo 如何帮助他们完成日常活动的一些例子。

总结和文档

简化代码审查过程:后台开发人员Gosia Ksionek展示了AI在她工作流程中的实际好处,通过使用 GitLab Duo 简化代码审查过程。她有效地利用GitLab Duo总结合并请求,使代码更改的审查变得更容易和更快速。除了总结合并请求外,Gosia还利用GitLab Duo回答编码问题并解释复杂的代码片段。这提高了她的生产力,帮助她更好地理解和管理复杂的代码库。通过这些演示,Gosia突出了GitLab Duo如何显著改善开发过程中的效率和清晰度,使其成为开发人员不可或缺的工具。

压缩评论线程:扩展软件开发副总裁Bartek Marnane使用 GitLab Duo 将冗长的评论线程压缩为简明摘要,确保在更新问题描述时捕捉到所有相关细节。

创建新文档:数据科学部门产品组经理Taylor McCaslin利用 GitLab Duo 为GitLab Duo本身创建了新文档,展示了一个提高清晰度和一致性的元用例,并大大减少了记录新功能所需的时间。

编写发布说明:产品规划高级产品经理Amanda Rueda使用GitLab Duo编写简短而有影响力的发布说明,突出更改及其对用户的价值。通过使用如下面这样精心设计的提示,Amanda增强了她的工作流程,确保每个发布说明都是清晰、简洁且以用户为中心,提升了整体沟通和用户体验:

“请为此更改创建一个两句话的摘要,用于我们的发布说明。语气应为对话式,并使用第二人称。摘要应包括问题或更改的描述,并与我们为你,用户,创造的价值相关联。”

以下是与 GitLab Duo 共同创建的一些发布说明的示例:

  • 扩展了路线图的排序选项
  • 现在可以使用里程碑和迭代来增强问题板的清晰度
  • 设计管理功能扩展到产品团队

优化文档站点导航:资深技术写作员Suzanne Selhorn利用 GitLab Duo 通过提供基于工作流的页面顺序来优化左侧导航。Suzanne向GitLab Duo提供了功能列表,生成了最佳顺序,并更新了左侧导航以匹配。 GitLab Duo 还比使用传统手动方法更快地起草了入门文档。

目标设定和团队对齐

起草和完善OKR:代码审查后端工程经理François Rosé发现GitLab Duo聊天在起草和完善OKR方面非常有价值。通过更清晰和有效地表达目标,François增强了目标设定和团队对齐。使用聊天,François确保每个OKR都是明确的、可执行的,并与团队的目标保持一致,从而提高了整体团队表现和凝聚力。以下是他使用的一个示例提示:

这是我打算创建的一个OKR:

目标:回顾回顾会议,促进团队繁荣
KR:测量100%团队成员的回顾满意度
KR:识别3个异步回顾的改进点
KR:实施1个改进
请提供如何改进这个目标和这些关键结果的直接反馈。

简化招聘和招聘流程:聊天帮助前端工程师Denys Mishunov制定了更新技术面试候选人电子邮件模板的明确简洁的文本。团队合作优化了沟通,以确保候选人获得所有必要信息,并使用合并请求进行。这个例子展示了AI工具在招聘流程中增强沟通的实际应用。

事件响应和配置

总结生产事件:现场可靠性工程师 Steve Xuereb 使用 GitLab Duo 总结生产事件并创建详细的事件回顾,从而简化文档编制过程。

创建样板 .gitlab-ci.yml 文件:Steve还使用聊天创建样板 .gitlab-ci.yml 文件,显著加快了他的工作流程。聊天作为一个有价值的伙伴,提出建议。此外,代码解释提供了详细的答案,在事件发生时很有帮助,提 高了他的生产力和对代码库的理解。

代码生成和测试

全栈开发:高级前端工程师 Peter Hegman 一直在使用代码建议进行 JavaScript 和 Ruby 开发。这突显了代码建议已成为开发人员跨越完整技术栈的强大工具。

生成Python脚本:Denys 进行了一个使用 GitLab Duo 完成非 GitLab 任务的实验。这个例子突显了我们的AI工具在典型软件开发任务之外的灵活性和实用性。

观看Denys如何使用 GitLab Duo 生成 Python 脚本以获取内容数据并将其存储在本地:

研究和支持

生成测试源代码:高级开发者倡导者 Michael Friedrich 使用 GitLab Duo 为 CI/CD 组件生成测试源代码。 以这种方式使用 GitLab Duo 有助于确保代码的一致性、良好的文档记录,并与我们的最佳实践保持一致。

简化研究任务 :我们的团队成员在有关于 GitLab 功能的问题时,经常求助于聊天,简化他们的研究和支持任务。Michael分享说,“当我有关于GitLab功能的问题时, 我会默认使用聊天,而不是打开 100 个浏览器标签。这种工作流程帮助我高效地在我们的社区论坛上协助用户。例如,我最近使用这种方法帮助一个用户进行SSH部署。” 使用聊天不仅节省时间,还提供快速、准确的信息,增强了我们为社区提供的支持。

功能测试

测试新功能:我们的工程师使用 GitLab Duo 测试新的功能,如代码建议中的Markdown支持。我们的一个团队成员指出,“我需要测试代码建议中的Markdown支持,以便在VS Code中编写博客文章和GitLab文档。我看到它已合并到17.0版本。”通过内部测试这些功能,我们确保它们在发布前达到我们的质量标准。

理解外部代码库

介绍外部项目解析功能:GitLab Duo的 /explain 功能,在帮助理解导入 GitLab 的外部项目方面极为有效。这一功能在 Michael 最近与开源专家 Eddie Jaoude 的直播中得到了重点介绍。Michael 表示:“我利用 /explain 功能来深入理解外部项目的源代码。我曾在直播中分享这一思路, 它有助于我们更好地了解开源项目及其依赖关系。”这一功能对于开发者而言,在快速掌握不熟悉的代码库及其依赖关系方面显得尤为珍贵, 极大地提升了他们的工作效率和代码理解能力。

其它

相关文章:

AI 辅助软件工程:AI IDE 辅助软件工程

示例

受限于模型能力,不同语言在能力上会出现差异。诸如于 Tabnine 的 支持语言 情况:

Language/frameworkCode completionsChat
JavaScript⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
TypeScript⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Python⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Java⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
C⭐⭐⭐⭐⭐⭐⭐⭐⭐
C++⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
C#⭐⭐⭐⭐⭐⭐⭐⭐
Go⭐⭐⭐⭐⭐⭐⭐⭐
Php⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Ruby⭐⭐⭐⭐⭐⭐⭐⭐⭐
Kotlin / Dart⭐⭐⭐⭐⭐⭐⭐⭐⭐
Rust⭐⭐⭐⭐⭐⭐⭐⭐⭐
React / Vue⭐⭐⭐⭐⭐⭐⭐
HTML 5⭐⭐⭐⭐⭐⭐⭐⭐
CSS⭐⭐⭐⭐⭐⭐⭐⭐
Lua⭐⭐⭐⭐⭐⭐⭐
Perl⭐⭐⭐⭐⭐⭐
YAML⭐⭐⭐⭐⭐⭐
Cuda⭐⭐
SQL⭐⭐⭐
Scala⭐⭐⭐
Shell (bash)⭐⭐⭐
Swift⭐⭐⭐
R⭐⭐⭐⭐
Julia⭐⭐
VB⭐⭐
Groovy⭐⭐
Matlab
Terraform⭐⭐⭐
ABAP

AI 辅助软件工程:准备

在开始编程之前,我们需要安装一些工具。这些工具将帮助我们编写代码、运行代码、调试代码等等。在这一章节中,我们将安装这些工具。

安装 Shire

Shire 是一种专门为 AI 设计的语言,用于促进大型语言模型(LLM)与集成开发环境(IDE)之间的通信,从而实现自动化编程。当前,Shire 语言只支持 JetBrian's IDE (诸如 IntelliJ IDEA,PyCharm,WebStorm 等 )。

因此,我们需要安装相关的 IDE,你可以选择其中一个来安装。在这里,我们选择 IntelliJ IDEA。随后,我们将安装 Shire 插件。

安装方式有三种:

  1. 在线安装。访问如下的链接,Shire - AI Coding Agent Language
  2. 插件市场安装。在 IntelliJ IDEA 等 IDE 的插件市场中搜索 Shire 插件并安装。
  3. GitHub 下载。从 Release 页面 下载插件的 zip 包,然后在 IDE 中选择安装插件。

插件市场安装示例:

Shire Install

配置 Shire

Shire 当前的配置项比较简单,只需要配置 OpenAI API 兼容的模型即可:

Shire Configure

运行 Shire

在安装好 Shire 插件后,我们可以在 IDE 中右键新建一个 .shire 文件,诸如 hello.shire,然后输入如下代码:

Hello, World!

接着,我们可以点击文件第一行的运行按钮,或者使用快捷键 Ctrl + Shift + R 来运行代码。

Run Shire

根据你的配置,Shire 将会调用模型对话,来生成内容。 如下图所示,红框区域是 OpenAI 地返回的结果:Hello! How can I assist you today?

Shire Run Result

当完成这些步骤后,我们就可以开始使用 Shire 构建我们的 AI IDE 了。

AI 辅助软件工程:重构代码示例

在软件开发过程中,重构是一种常见的实践,旨在改善代码的质量、可维护性和可读性。AI 辅助重构工具可以帮助开发人员自动识别和执行重构操作,从而提高开发效率和代码质量。

AI 重构是指利用人工智能技术来识别和执行代码重构操作的过程。AI 重构工具通常基于大型语言模型(LLM)和机器学习算法,能够分析代码库中的模式和结构,并生成重构建议。

在现有情况下,适合的 AI 重构场景应该具备以下特点:

  • 可读性重构,即重构的目标是提高代码的可读性和可维护性。
  • 意图驱动的重构,即用户应该提供明确的重构目标和意图,以便 AI 工具能够生成准确的重构建议。
  • 代码坏味道修复,借助传统工具或者 AI 工具识别代码中的坏味道,并提供相应的重构建议。
  • 模式识别和重构,借助三方工具识别到设计问题,并提供相应的重构建议。

在复杂上下文下,如大量继承关系、复杂的代码结构等,AI 重构工具的效果可能会受到限制。因此,开发人员需要在使用 AI 重构工具时,提供足够的上下文信息,以确保生成的重构建议准确和可靠。

AI 重构

AI 重构是指利用人工智能技术来识别和执行代码重构操作的过程。AI 重构工具通常基于大型语言模型(LLM)和机器学习算法,能够分析代码库中的模式和结构,并生成重构建议。

AI 重构的优势

AI 代码重构的优势如下:(Tabnine 总结

  1. 提高效率:AI驱动的重构工具能够快速处理和分析大型代码库,比人类开发者更快地识别出需要改进的区域。
  2. 提升代码质量:通过一致地应用最佳实践和编码标准,AI重构工具有助于整体提升代码质量。它们可以发现并修复代码异味、冗余代码和其他在手动重构过程中可能被忽略的问题。
  3. 改进可维护性:AI重构可以持续进行,确保代码库保持干净和有序。这提高了代码的可读性,降低了新团队成员的学习曲线,并有助于项目的长期可持续性。
  4. 减少错误:自动化重构可以最大限度地减少手动重构过程中可能发生的人为错误。AI工具可以确保重构不会引入新的错误,从而维护代码的功能完整性。
  5. 代码库的一致性:AI驱动的重构工具可以在大型项目的不同部分或组织内的多个项目中强制执行一致的编码风格和实践。
  6. 节约成本:通过减少代码维护所需的时间和精力,AI重构工具可以带来显著的成本节约。这使公司能够更有效地分配开发资源,将资源从维护转向创新。

但是往往在实际使用中,我们发现 AI 重构工具的效果并不如人工重构那么好。这是因为 AI 重构工具缺乏足够的上下文信息,无法理解代码的意图和结构,导致生成的重构建议不够准确和可靠。

AI 重构的瓶颈:依赖于有效上下文

如果你探索过使用 AI 来构建代码时,你会发现:AI 懂的重构手法你都懂,但是看别人使用 AI 重构似乎非常顺手。这是为什么呢? 重构通常依赖于好的上下文, 即需要开发人员拥有大量的先验经验。

意图驱动的重构

简单来说,当你缺少一个代码改进的方向时,无法给 AI 一个明确的意图,剩下的就要靠 AI 随机了 —— 因此,大部分情况下,AI 只是进行简单的重命名、方法提取之类基本的重构手法。而:

  • 如果你告诉 AI,你要重构多个 if 到策略模式,那么它就会给你生成策略模式的代码。
  • 如果你给了 AI 对应的继承关系,那么它就会考虑到继承关系。
  • 如果你给了 AI 一些坏味道,那么它就会考虑到坏味道。

理解这一点,在工具上实现辅助重构就变得非常简单了。

基于聊天的重构上下文

如下是 Tabnine 通过聊天提供的上下文:

  • 你之前的问题或 prompt
  • 当前文件中选定的代码块(或光标位置)
  • 当前打开的文件及其他打开的文件
  • 当前对话的聊天记录,包括所有之前的问题和答案
  • 当前用户工作区中的相关文件或代码块
  • 运行时错误
  • 导入的库
  • 编译/语法错误
  • 非代码来源的信息
  • 当前选定的代码
  • 已连接的存储库
  • 对话历史
  • Git 历史
  • 项目元数据和其他项目文件

对于其它 AI 编码工具来说,其也是非常相似的。部分工具,诸如于 Tabnine,还提供了更高级的方式去获取上下文

  • Tabnine 的企业版还会从已连接的存储库中获取全局上下文。
  • 你可以微调你的私人 Tabnine 模型,以获得更加个性化的 AI 重构工具。

总之,就是尽可能提供关键有效的上下文信息,以便 AI 能够更好地理解你的意图。

基于代码坏味道的重构

ArchGuard

指标体系

  • 体量维度。过大的方法、过大的类、过大的包、过大的模块
  • 耦合维度。枢纽模块、枢纽包、枢纽类、枢纽方法、数据泥团、过深继承、循环依赖
  • 内聚维度。霰弹式修改、数据类
  • 冗余维度。冗余元素、过度泛化
  • 质量维度。包含休眠的测试、被忽略的测试、缺乏校验的测试、包含繁杂判断的测试、包含冗余打印的测试、静态方法

Code Health

Code Health – How easy is your code to maintain and evolve?

Code Health

AI 重构功能设计

对于习惯使用重构来改善既有代码可读性的开发人员来说,经常使用的重构手法有:

  • 提取方法:将重复的代码片段提取到单独的方法中,提高代码的可重用性和可读性。
  • 重命名:为变量、方法、类等提供更有意义的名称,使代码更易于理解。
  • 内联方法:将方法调用替换为方法体,减少不必要的方法调用。
  • 移动方法:将方法从一个类移动到另一个类,以更好地组织代码。
  • 提取变量:将复杂的表达式提取为一个变量,提高代码的可读性。

这些重构手法是开发人员在日常工作中经常使用的,它们有助于改善代码的质量、可维护性和可读性。

重命名建议

如下是 AutoDev 中重命名建议的示例:

AutoDev Rename

它可以把当前代码作为上下文,发给 AI 模型,然后返回重命名的建议。

重新组织示例

当你使用 AI 重构时,会发现因为 AI 做了重命名等操作,没有修改 ref 导致代码无法运行。因此,你无法直接应用 AI 的重构建议。 基于此, AutoDev 通过提供 DevIns AI Agent 语言,使得你可以直接执行重构代码:

/refactor:rename crtBlog to CreateBlog

如下图所示:

AutoDev Refactor

它使得你可以直接执行重构代码,而不需要手动修改代码。

AI 重构功能实现: Shire 示例

在这里我们依旧使用 Shire 作为我们的 AI IDE 重构工具。Shire 语言提供了一种简便 AI 编码智能体语言,能够让大型语言模型(LLM)与控制集成开发环境(IDE)之间自由对话,以实现自动化编程。

步骤 1. 一个简单的示例

如下是一个基础示例,展示了如何使用 Shire 插件来构建一个简单的 AI 辅助开发人员的指令。只需要在 IDE 中新建一个 Shire 文件,然后将以下内容复制到文件中:

请你这段代码建议适当的重构。提高代码的可读性、质量,使代码更加有组织和易懂。

```java
public class Main {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        int c = a + b;
        System.out.println("Sum: " + c);
        int d = a - b;
        System.out.println("Difference: " + d);
        int e = a * b;
        System.out.println("Product: " + e);
        int f = b / a;
        System.out.println("Quotient: " + f);
    }
}
```

就可以直接在 IDE 中运行 Shire 插件,获取到 AI 重构的结果。如下是零一万物 API 返回的结果

public class Main {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        
        int sum = add(a, b);
        System.out.println("Sum: " + sum);
        
        int difference = subtract(a, b);
        System.out.println("Difference: " + difference);
        
        int product = multiply(a, b);
        System.out.println("Product: " + product);
        
        int quotient = divide(b, a);
        System.out.println("Quotient: " + quotient);
    }
    
    public static int add(int a, int b) {
        return a + b;
    }
    
    public static int subtract(int a, int b) {
        return a - b;
    }
    
    public static int multiply(int a, int b) {
        return a * b;
    }
    
    public static int divide(int a, int b) {
        return a / b;
    }
}

在上述示例中,AI 重构工具 Shire 对原始 Java 代码进行了以下改进:

  • 提取方法:将重复的计算逻辑提取到单独的方法中,提高了代码的可重用性和可读性。
  • 命名改进:为变量和方法提供了更有意义的名称,如 sumdifferenceproductquotient ,以及 addsubtractmultiplydivide,使得代码意图更加清晰。
  • 代码组织:通过将计算逻辑放入单独的方法,使得 main 方法更加简洁,易于理解。

通过这些重构,代码变得更加模块化,易于维护,并且对于其他开发者来说也更加易于理解。这种重构不仅提高了代码的质量,也使得未来的修改和扩展变得更加容易。

步骤 2.将代码转变为变量方式

步骤 1 的代码是我们写死的,为了更加通用,我们可以将代码转变为变量方式:

请你这段代码建议适当的重构。提高代码的可读性、质量,使代码更加有组织和易懂。
    
$selection

随后,可以配置到右键菜单中,如下:

---
name: "重构代码"
actionLocation: ContextMenu
---

请你这段代码建议适当的重构。提高代码的可读性、质量,使代码更加有组织和易懂。
    
$selection

如此一来,我们就可以在 IDE 中右键选择代码,然后直接进行重构。

PS:当前的 Shire 插件为了确保性能,需要用户重新启动 IDE,才可在右键菜单中看到新的菜单项。

步骤 3. 丰富我们的 prompt

如果你不熟悉如何针对代码进行重构,可以参考一些主流工具的重构提示词。如下是我们结合了 JetBrains AI Assistant 的提示词所构建的 prompt:

---
name: "Refactoring"
actionLocation: ContextMenu
interaction: ReplaceSelection
---

请你这段代码建议适当的重构。提高代码的可读性、质量,使代码更加有组织和易懂。你的回答应包含重构描述和一个代码片段,展示重构后的结果。
使用一些众所周知的重构技巧,比如以下列表中的一个:

- 重命名
- 修改签名、声明
- 提取或引入变量、函数、常量、参数、类型参数
- 提取类、接口、超类
- 内联类、函数、变量等
- 移动字段、函数、语句等
- 上移构造函数、字段、方法
- 下移字段、方法

请勿生成多个代码片段,尝试将所有更改都整合到一个代码片段中。
请勿生成包含虚构周围类、方法的代码。不要模拟缺失的依赖项。
提供的代码已经整合到正确且可编译的代码中,不要在其周围添加额外的类。

重构以下代码:

$selection

而在某些情况下,我们实际上可以从 IDE 及其插件中拿到更多的上下文,诸如于代码坏味道、代码依赖关系、代码结构等

步骤 4. 添加代码坏味道

在 Shire 中可以通过 $codeSmell 变量来获取相关代码的坏味道信息,如下:

这里有一些相关的 Code Smell

$codeSmell

当代码中有一些坏味道时,我们可以通过这种方式来提示 AI 重构工具。

这里有一些相关的 Code Smell

// - Method 'updatePost(java.lang.Long, com.phodal.shire.demo.entity.BlogPost)' is never used
// - String can be replaced with text block

有了上述的信息之后,AI 就能给我们更好地重构建议。

Shire 的相关代码实现,依赖于 IDE 的接口。因此,你也可以安装一些插件来做 lint,以提供更多的上下文信息。

其它

JetBrains 重构的提示词示例

You should suggest appropriate refactorings for the code. Improve code readability, code quality, make the code more organized and understandable. 
Answer should contain refactoring description and ONE code snippet with resulting refactoring.  
Use well-known refactorings, such as one from this list:
- Renaming
- Change signature, declaration
- Extract or Introduce variable, function, constant, parameter, type parameter
- Extract class, interface, superclass
- Inline class, function, variable, etc
- Move field, function, statements, etc
- Pull up constructor, field, method
- Push down field, method.
Do not generate more than one code snippet, try to incorporate all changes in one code snippet. 
Do not generate mock surrounding classes, methods. Do not mock missing dependencies. 
Provided code is incorporated into correct and compilable code, don't surround it with additional classes. 
Refactor the following code:

PS:AutoDev 基于 JetBrains 的 AI Assistant 这个提示词来编写重构功能。

AI 辅助软件工程:研发数字化

示例

Haiven

https://www.thoughtworks.com/en-sg/what-we-do/ai/ai-first-software-delivery/Haiven_team_assistant

Replit Teams

Unblocked

Usecase:

  • 新员工入职。Unblocked 帮助新团队成员找到所需答案,以便他们可以立即开始贡献。
  • 征服遗留代码。Unblocked 将您的代码与其历史联系起来,以便您的团队在进行更改之前了解其影响。
  • 自动化内部支持。通过使跨职能团队能够自主回答问题,保持工程团队专注于他们的工作。

Knowledge Management

尽管现有许多开发工具,开发团队仍然面临显著的效率问题,特别是在找到和保持代码库的共同理解上。频繁的打断和分散的代码相关信息导致延误和挫败感。比如 Retool 的 2022 年工程时间状态 调查显示,大量开发者的时间被浪费在寻找正确的上下文和代码所有权信息上。Unblocked 旨在解决这个特定的低效问题,通过减少搜索信息和等待同事回复的时间,帮助开发者最大化他们的生产力。

什么:Unblocked 提供的解决方案

Unblocked 是一个开发者工具,设计用来提供关于特定代码库的准确和有帮助的答案。不同于提供通用答案的通用型大型语言模型(LLM),Unblocked 连接到构建应用程序时使用的系统,如 GitHub、Jira、Slack 等,以提供精确的答案。它使用针对代码库优化的大型语言模型,理解代码库的细微差别和具体内容。Unblocked 支持多种集成,包括 GitHub、Bitbucket、Jira、Linear、Slack、Confluence 和 Stack Overflow for Teams,并计划未来支持 GitLab 和 Notion。此外,Unblocked 还具有创建和引用与代码文件相关的视频的功能,使视频内容在 IDE 中易于发现。

如何:Unblocked 的实现和功能

  1. 与多个数据源集成:Unblocked 连接到存储代码相关对话和信息的各种系统,包括源码管理平台、问题跟踪器和通信工具。这样,它可以聚合并检查所有连接的内容,提供准确和上下文丰富的答案。

  2. 优化的 LLM:通过使用针对特定代码库优化的 LLM,Unblocked 能够理解并响应有关代码的详细查询,比如特定的实现细节和设计决策。

  3. 无缝访问:Unblocked 确保通过多种界面轻松获取答案:macOS 应用程序、IDE 插件(如 Visual Studio Code)以及直接在 Slack 中。这使得开发者无需离开当前的工作流程就能获得所需信息。

  4. 主动知识呈现:即使开发者不知道具体要问的问题,Unblocked 也能主动呈现相关讨论和信息,确保他们在处理代码库的不同部分时拥有必要的上下文和理解。

  5. 视频集成:Unblocked 允许创建解释代码库部分内容的视频。这些视频与录制过程中引用的相关文件和内容链接,使其在 IDE 中易于发现。每个视频还包含转录和可链接的时间索引,方便快速导航。

通过解决开发工作流程中的特定低效问题,Unblocked 旨在显著提高生产力,减少开发者花在搜索信息上的时间,从而让他们更多地专注于编写代码。

AI 辅助软件工程:知识管理

行业现状

Atlassian Rovo 通过生成式 AI 解锁企业知识的工具;它以负责任的方式处理数据,管理员可控制访问权限,确保保密信息的隐私安全。

Atlassian Rovo

  • 创建及审查智能体:负责生成、审核并优化各种通信、产品规格、目标设定等领域的智能体。
  • 工作流程管理智能体:自动化和简化多项任务,如自动为新请求创建设计草稿,或在 Jira 问题上进度更新时自动执行相关操作。
  • 知识管理智能体:自动解答问题,整合研究成果至 Jira 规格文档,自动生成服务清单,并为自定义知识库提供内容。
  • 团队文化智能体:协助新成员融入团队,培育感恩文化,促进团队间的协作。
  • 维护智能体:高效处理诸如清理 Jira 积压任务、整理 Confluence 页面,以及确保内容符合格式规范等耗时任务。
  • 自定义智能体:用户可直接利用 Rovo 智能体通过无代码界面自行创建所需智能体,或在 Atlassian 市场上探索多样化的智能体选项。

AI 辅助软件工程:提交信息与研发数字化

理解

合理的提交信息

---
name: "Commit message"
description: "生成提交信息"
interaction: AppendCursor
actionLocation: CommitMenu
---

为给定的变更(Diff)编写一个连贯但具有描述性的代码提交信息。

- 确保包含修改了什么以及为什么。
- 以不超过 50 个字符的祈使句形式开头。
- 然后留下一个空行,如有必要,继续详细说明。
- 说明应该少于 200 个字符。

遵循常规提交规范,例如:

- fix(authentication): 修复密码正则表达式模式问题
- feat(storage): 添加对S3存储的支持
- test(java): 修复用户控制器的测试用例
- docs(architecture): 在主页添加架构图

Diff:

$currentChanges

JetBrains 示例

提交信息:

Your task is to generate a well-read summary of changes made in the project.
The paragraph should have less than 10 sentences and less than 300 words. Summarize the following commit messages.

Given the below code differences (diffs), please generate a concise, clear, and straight-to-the-point commit message.
Make sure to prioritize the main action.
Avoid overly verbose descriptions or unnecessary details.
Start with a short sentence in imperative form, no more than 50 characters long.
Then leave an empty line and continue with a more detailed explanation.
Write only one sentence for the first part, and two or three sentences at most for the detailed explanation.

AI 辅助软件工程:需求智能化

行业现状

需求与项目管理 - Atlassian Intelligence

  • 洞见发现
    • 在 Jira 中使用自然语言快速查找问题及其依赖关系
    • 运行复杂查询、总结图表数据并获取趋势建议
    • 理解警报、识别模式并适当升级相关事项
  • 工作效率提升
    • 将笔记转化为有用文档,总结页面内容和评论,快速创建行动项目
    • 加快撰写项目计划、用户故事、拉取请求等
    • 获取当前工作的简明上下文
    • 根据受众调整语气风格
  • 利用 AI 推动行动
    • 与虚拟助理协作响应知识库中的问题,提供更快的服务
    • 使用 AI 辅助设置服务台,快速支持员工和客户
    • 使用自然语言轻松创建自动化流程,解释要求或操作步骤

AI 辅助平台工程

案例

项目协作工具:GenPen.AI

https://genpen.ai/

GenPen.AI 是一个项目协作与代码生成工具。它可以将设计提示转化为REST API,并自动生成文档。核心功能包括:代码生成、基于AI的多模式VLLM转换器、OpenAPI集成、自动化Git、代码和文档管理、多个AI代理用于响应汇总。它的目标是加快调试速度,减少开发时间,并简化项目管理。GenPen AI自动化重复任务,利用AI转换器,并根据模型生成代码,从而减少开发时间。 图片

AI工作流程编排:LangBase

LangBase 为用户提供了一站式的 AI 应用管理和运维服务,降低用户创建 AI 应用的成本。因此 LangBase 不仅在底层提供提供了模型和应用的管理,也在应用平台之上多提供了一层业务接入层,最大化的降低用户创建和使用 AI 应用的成本。

Neon 文档问答

Mistral 7B and BAAI on Workers AI vs. OpenAI Models for RAG

RAG 过程

生成 Embedding

  • 目的:通过 Embedding 模型,将用户的查询转换成查询向量。
  • 功能:Embedding 模型将文本转化为数值形式,便于系统据此搜寻相关信息。

上下文检索

  • 目的:利用相似性搜索技术,在文档或数据库中寻找与查询相关的信息。
  • 功能:系统会从外部资源中搜索,寻找与查询向量高度一致的数据。

完成(或文本生成)

  • 目的:结合用户查询和检索到的上下文信息,生成回答。
  • 功能:生成模型运用查询及附加上下文,形成既详尽又准确的回答。

对比与总结

上下文生成质量:

  • bge-base-en-v1.5text-embedding-ada-002 模型生成的上下文在一定程度上相似,特别是在小规模文本块(k=3)时相似度更高。
  • 随着文本块数量增加,相似度下降。

生成文本质量:

  • gpt-3.5-turbo 在文本生成质量上的评分显著高于 mistral-7b-instruct-v0.1
  • 尽管上下文相似,生成文本会因模型的随机性设置而有所不同。

评价方式:

  • 上下文质量主要通过相似度分析进行评估。
  • 文本生成质量通过主观调查进行评估,反映了用户实际体验。

AI 辅助 UI 设计

示例

Tango + AI Agent Workflow

AI 辅助的团队开发工作流思考

在网易云音乐内部,结合我们对业务需求特点的梳理,和开发者的实际诉求,我们构建了渐进式的低代码能力,专注于降低技能门槛,减少编写重复代码。我们从2023年4月开始探索 AI Code 能力与开发者个人工作流的结合,包括引入 Github Copilot 提升源码开发体验,通过 Tango 与 GPT 系列大模型的连接来提供 AI 驱动的 Low Code 能力。

在2024年,我们进一步的开始探索借助 AI 来升级现有的团队开发工作流,从大前端场景覆盖到服务端源码开发场景,在内部协同 LangBase 来提供 DevAgent(生成页面,生成组件,生成代码片段)、DesignAgent(抠图,生图,设计稿转代码) 等能力,与 CodeMaker 共建的方式来逐步取代 Github Copilot,为团队定制专属代码补全模型,并持续探索 AI Code 能力与团队开发工作流的深度集成和定制。

images

如上图所示,在大前端的开发工作流场景中,海豹D2C[3] 提供了基于设计稿直接生成项目源码的能力,目前支持 React, ReactNative, Vue 等多种框架,支持内部核心的C端场景覆盖,借助 DesignAgent 能力,我们增强了对设计稿的识别精度,提升了出码还原度。在 Tango 这一层,我们并没有一味追求可视化开发的思路,而是通过衔接既有的源码开发工作流,并借助 LangBase 提供的 DevAgent 来增强代码生成能力,在本地开发流程中通过完善源码开发环节的 DevTools 和 CodeMaker 能力来改善开发者体验。

当前我们正尝试从四个方面将 AI Code 能力融入到团队开发工作流中,具体包括训练自定义补全模型(针对不同的开发者画像提升补全覆盖率和接受率)、CM插件扩展(集成核心的工具设施到IDE,实现对话式信息获取和配置生成)、CM工作流扩展与自定义(复用和下发既有的Agent能力)、AI向导(提供特定领域内容的自动化生成能力)等四个方面。

UI 代码生成

示例

示例:Quest AI

https://www.quest.ai/

Quest AI 的模型可以基于设计稿或草图生成真实、有用的代码。它包含所有专业开发人员关心的事情。使用我们的聊天提示来修改样式、编写业务逻辑并连接到您的后端。Quest是为开发者设计的。它自动化了构建应用程序的繁琐部分,同时又让您拥有完全的控制权,这样您就可以构建任何您想要的东西。

示例:V0

https://v0.dev/

v0是一个由 Vercel 提供支持的基于 AI 的生成式用户界面系统。它基于 shadcn/ui 和 Tailwind CSS 生成易于复制粘贴的 React 代码,供人们在其项目中使用。v0 使用 AI 模型根据简单文本提示生成代码。在提交提示词后,它会为你提供三份由 AI 生成用户界面。你可以选择其中一个并复制粘贴其代码,或进一步完善它。要进行完善,你可以选择生成的 UI 的各个部分来微调您的创建。准备好后,您可以复制、粘贴并发布。V0 是根据 Vercel 团队编写的自定义代码与开源和合成数据集混合训练的。Vercel 可能会使用用户生成的提示和/或内容作为第三方提供商的模型和学习系统的输入,以改进他们的产品。

UI 交互生成

低代码生成

示例

IBM Assistant Builder

Watsonx Orchestrate 中的 AI 助手构建器是新一代构建工作室,它利用生成式 AI 和数字技能的强大功能,帮助组织和领域专家通过强大的低代码体验快速轻松地创建新的、引人注目的 AI 助手。通过定制的 AI 助手,客户和员工可以在高度互动的自然语言体验下,无缝地完成任务和复杂流程。

Watsonx Orchestrate 中的 AI 助手构建器体验为构建者提供了一个低代码生成式 AI 和自动化工作室,可以快速建立基于大型语言模型(LLM)驱动的助手,这些助手扎根于业务背景、数据和自动化。AI 助手构建器使您能够通过高度对话化的界面扩展您的自动化投资,并通过注入您信赖的 AI 来扩大应用范围。生成式 AI 功能由 IBM 值得信赖且透明的大型语言模型本地提供,并针对特定业务功能进行了微调。构建者可以灵活控制何时以及如何使用大型语言模型,包括选择基础语言模型、内容支撑、AI 引导的操作和对话技能。IBM Watsonx Orchestrate 为您的客户和员工提供自然、优化的体验,引导他们完成多步骤流程,同时让生成式 AI 处理繁重的任务。

  • 对话式搜索利用生成式 AI。AutomaConversational Search 通过运用大型语言模型(LLM)进行检索增强生成(RAG),旨在生成准确、符合您公司内容的对话式回答,并具备答案追踪功能,确保信息准确且可验证。
  • 对话技能。Watsonx Orchestrate AI 助手构建器中定制的AI助手能够在对话中直接执行自动化任务,或称为技能。生成式 AI 在运行时无缝收集执行任务所需的输入,为用户提供更流畅的体验。
  • AI引导的操作。通过为您的助手提供特定短语,精确控制何时利用 LLM 的强大功能。这些短语将自动触发针对特定用例的AI驱动响应,例如提供产品和服务建议、解释关键概念等。
  • 基础 LLM。使用 IBM 的 Granite 模型系列,或从精选的其他 LLM 列表中选择,为您的助手提供生成式AI能力。通过添加特定的提示指令,生成最佳的生成式回答,或在无代码界面中优化 LLM 输出,以增加灵活性。

AI 辅助软件工程:AI 辅助开发

数据驱动的需求

Google 智能粘贴

Smart Paste for context-aware adjustments to pasted code

对 Google 单体代码库(Google 的代码库,存储完整的工作历史,而不仅仅是提交的更改)的分析揭示了用户行为中一些有趣的模式,这些模式是提高效率的潜在目标。 例如,根据编辑历史记录,约 25% 的粘贴内容会立即进行修改,这些修改范围从小的语法修正(例如,添加缺失的分号)到更复杂的适应周围代码环境的调整 (例如,重命名变量和更改其类型)。进行此类更改通常会打断代码创作的流程并减慢开发过程。

考虑到这一点,我们推出了Smart Paste,这是一种现在在 Google 广泛使用的工具,它可以预测代码环境的下一状态,并使用生成式 AI 对粘贴的代码进行上下文感知的调整。 利用大序列模型的最新进展——例如DIDACT,该进展使代码审查、构建修复等工具成为可能——Smart Paste 简化了代码修订过程中的复制粘贴流程。 在一项涵盖约 4 万名采用该功能的工程师的使用研究中,我们发现 6.9% 的 IDE 粘贴操作使用了 Smart Paste,并且有 42.5% 的接受率,这显著简化了用户的工作流程。

JetBrains 报告

Developers save up to 8 hours per week with JetBrains AI Assistant

JetBrains Top 5 Features:

架构

WebIDE

Replit Arch

跨 IDE 设计

The Self-Driving IDE is Coming

Features x IDEsVS CodeJetBrainsNeovimXcodeEmacsAndroid Studio
Chat       
Completions       
Commands       
Inline Edits       
Chat history       
Enterprise controls       
Custom prompts       
       

示例:Cody 的 IDE 架构总结

CCB 架构如下:

Cody 架构示例

在 Sourcegraph,我们的目标是构建一个通用的解决方案,将 Cody 编码助手集成到各种 IDE 中,这涉及到一套战略性的架构设计,以减轻通常与此类工作相关的复杂性和成本。关键组件和策略如下:

  1. 辅助二进制架构

    • Cody 客户端后端 (CCB):包含大部分业务逻辑的核心组件,可在不同的 IDE 之间共享。主要用 TypeScript 和 Rust 实现。
    • 瘦客户端:与 CCB 交互的 IDE 特定客户端,尽量保持 IDE 实现的简单化。
  2. 协议和通信

    • JSON-RPC 协议:用于 CCB 和 IDE 客户端之间的通信。该协议包含许多请求和通知,以处理各种功能,如聊天、补全、编辑等。
    • 复杂的客户端需求:每个新功能都需要在客户端进行详细而复杂的实现,包括用户界面、错误处理、身份验证和 IDE 特定的控制。
  3. 以 VS Code 为参考模型

    • VS Code API:由于其现代且可扩展的设计,被选为 Cody 协议的主要模型。
    • 模拟 VS Code 环境:对于非 VS Code 的 IDE(如 JetBrains),在 Node.js 中运行 VS Code 扩展,创建一个模拟的 VS Code 环境,通过 CCB 与实际 IDE 通信。
  4. 状态管理和实时更新

    • 有状态协议:Cody 的架构需要维护用户编辑会话的实时镜像,以提供响应快速且上下文感知的辅助。
    • 实时通信:IDE 状态与 CCB 的持续同步,以实现即时反馈和交互。
  5. 挑战和目标

    • 高工程开销:为 IDE 开发新的 Cody 客户端资源密集,通常需要 6 到 9 个月,因为涉及广泛的功能集和复杂的协议要求。
    • 雄心勃勃的设计:该架构既创新又具有争议,平衡了提供丰富用户体验的需求与开发和维护此类综合系统的实际限制。
  6. 受 LSP 启发但有所扩展

    • 超越 LSP:虽然受语言服务器协议 (LSP) 启发,但 Cody 的需求远远超出了 LSP 所能提供的范围,需要一个更广泛且多功能的协议来处理 IDE 的所有功能。

总的来说,Sourcegraph 的 Cody 架构反映了一个深思熟虑的选择,即通过深入的集成和复杂的实现来实现跨多个 IDE 的无缝且强大的编码助手体验。

AI 辅助软件工程:代码补全

示例

补全插件示例:GitHub Copilot

GitHub Copilot Architecture

  • 对于编辑器输入的边界判断,包括太少、太多、取消等等很多场景齐全的考虑
  • 缓存思想,利用多级缓存策略保护后台,模型运算本身就是一件昂贵的事情
  • prompt的设计,不仅仅包含了上下文代码,在文件解析、编辑器打开的相关代码上还做了很多
  • 利用简单的Jaccard算法计算分词后的文本相似度,能够快速决策出当前上下文相关的snippet
  • 实验特性,在Copilot中,大量的参数、优先级、设置字段都是通过实验来控制的,有一套完整的监控上报体系,帮助Copilot去调整这些参数,以达到更好的效果

补全插件示例:Cody

结合《The lifecycle of a code AI completion

每个Cody补全都经过以下四个步骤:

  • 规划 - 分析代码上下文以确定生成补全的最佳方法,例如使用单行补全还是多行补全。
  • 检索 - 从代码库中查找相关代码示例,为LLM提供最合适的上下文。
  • 生成 - 使用LLM根据提供的提示和上下文生成代码补全。
  • 后处理 - 对AI生成的原始补全进行细化和过滤,以提供最相关的建议。

Cody的目标是提供与开发者工作流程无缝集成的高质量补全。

Class Implementation as Context

详细步骤如下:

  1. 规划阶段:
    • 上下文准备: 根据上下文确定生成自动补全建议的最佳方法。这涉及使用启发式和规则将请求分类为单行或多行补全。
    • 语法触发器: 使用诸如Tree-sitter之类的工具分析代码结构,确定精确的语法线索,影响补全行为。
    • 建议小部件(Suggestion widget)交互: 利用与建议小部件的交互(例如在VS Code等IDE中)来增强补全建议的相关性和可用性。
  2. 检索阶段:
    • 上下文检索: 从编辑器上下文中收集相关的代码示例,例如最近查看的文件或打开的选项卡。
    • 优化: 使用滑动窗口 Jaccard 相似性搜索等技术,根据与当前光标位置相关的相关性检索和排名代码片段。
    • 上下文嵌入: 尝试使用嵌入索引等技术来提高上下文理解和补全建议的相关性。
  3. 生成阶段:
    • 模型利用: 使用 Claude Instant 等大型语言模型(LLM)根据提供的提示生成代码补全。
    • 改进: 解决 FIM "填充中间" 支持、减少延迟和质量调整等挑战,通过优化提示结构和理解模型响应动态。
    • 降低延迟: 实施 Token 限制、stop-words、流式响应和高效的 TCP 连接处理等策略,以减少端到端的延迟。
  4. 后处理阶段:
    • 质量保证: 应用后处理技术来优化生成的补全。
    • 内容改进: 避免重复内容,适当截断多行补全,并使用语法分析和概率评分评估补全的相关性。
    • 过滤: 实施过滤器来移除明显低质量的补全建议,同时确保在显示足够相关建议和不过度展示之间取得平衡。

每个阶段在提升 Cody 代码补全功能的整体质量、速度和用户体验方面都发挥着关键作用,旨在利用先进的人工智能能力,同时优化代码编辑环境中的实际使用场景。

补全插件示例:Continue

文章:How can you improve the code suggestions you get from LLMs?

在使用 LLM(大型语言模型)工具时,有几点需要注意,以确保获得高质量的代码建议并避免错误。Josh Collinsworth 在他的文章中提出了一些值得关注的问题和改进方法,以下是总结和一些建议:

  1. 提供明确而全面的指示(prompt)

    • 优点
      • 如果你很了解自己在做什么,这个方法很容易操作。
      • 可以根据具体情况进行定制。
    • 缺点
      • 指示可能需要非常精确,以至于直接写代码更容易。
      • 过程缓慢且繁琐,每个人每次都要重复进行。
  2. 添加系统消息,包含应始终遵循的指示

    • 优点
      • 可以设置一次,然后忘记(类似于环境变量)。
      • 对许多事情效果很好(例如操作系统版本)。
    • 缺点
      • 很难事先预测所有可能的指示。
      • 由于上下文长度限制,系统消息中的信息量有限。
  3. 自动过滤明显错误的建议,并请求新建议

    • 优点
      • 可以确保代码不违反许可证,使用特定库等。
      • 过滤器捕获建议时,可以自动重新提示。
    • 缺点
      • 很难事先确定哪些过滤器是必要且充分的。
      • 过滤系统可能会变得庞大,导致运行缓慢且成本高。
  4. 改进从代码库和软件开发生命周期中检索和使用上下文的方式

    • 优点
      • 有很多指南可以帮助建立基本的RAG系统。
      • 使用文档和代码片段作为上下文可以减轻知识截断问题。
    • 缺点
      • 构建一个能够即时自动确定相关上下文的系统很困难。
      • 可能需要很多集成,并且必须永久维护。
  5. 使用不同的 LLM 并使用多个 LLM

    • 优点
      • 大多数 LLM 工具使用 1-15B 参数模型进行代码补全,并使用 GPT-4 回答问题。
      • 可以针对特定情况使用模型(例如专有编程语言)。
    • 缺点
      • 可能无法使用你想要和需要的模型。
      • 你需要的许多模型可能根本不存在。
  6. 通过微调改进现有的LLM

    • 优点
      • 可以使模型学习你的首选风格。
      • 可以针对每个用例进行高度定制。
    • 缺点
      • 可能需要人们生成大量领域特定的指示和 100+GPU 小时。
      • 在学习新知识/能力方面效果不佳。
  7. 使用领域自适应继续预训练改进开源LLM

    • 优点
    • 缺点
      • 可能需要数十亿个相关公司数据的标记和数千个GPU小时。
      • 这是一个具有挑战性、昂贵且耗时的方法。
  8. 从头开始预训练自己的LLM

    • 优点
      • 可以通过预处理训练数据决定学习哪些知识/能力。
      • 这是创建最好的模型(如 GPT-4 和DeepSeek Coder)的方法。
    • 缺点
      • 可能需要数万亿个互联网数据的标记和相关公司数据,以及数百万个GPU小时。
      • 这是最具挑战性、昂贵且耗时的方法。

结论: 为了确保我们的代码助手不会落下任何乘客,我们需要更高的可配置性,比目前大多数AI代码辅助工具提供的更多。若系统中的任何部分不在你的控制之下, 你会发现建议可能会随时发生变化。我们需要采用以上列出的所有方法,以确保代码助手能够持续改进和适应用户需求。

示例:RepoFuse

蚂蚁 CodeFuse 代码大模型技术解析:基于全仓库上下文的代码补全

本文提出一种仓库级别代码补全框架RepoFuse:通过对实际编程的总结抽象,我们的方法从仓库中抽取了两种关键的跨文件上下文:基于代码相似性分析的相似上下文 (Similar Context),用于识别功能相近的代码段;以及语义上下文(Semantic Context),提供类别分类和 API 交互的语义理解。然而, 如此大量的信息可能导致模型的输入过于冗长,影响推理生成的效率。为此,RepoFuse采用了一种基于相关性引导的上下文选择策略(Relevance-Guided Context Selection) 指导模型 Prompt 的构建。这种技术有选择地筛选出与当前任务最相关的上下文,将上下文精炼为简洁的 Prompt,既能适应有限的上下文长度,又能确保高完成度的准确性。

GitHub: https://github.com/codefuse-ai/RepoFuse

RepoFuse 的工作流程如图所示,分为三个阶段:Semantic Context Analysis、Similar Context Retrieval 和 Relevance-Guided Context Selection

以下是每个阶段的总结:

  1. Semantic Context Analysis。在代码补全任务中,缺乏跨文件的依赖信息可能导致模型产生幻觉(即生成不准确的代码)。为解决这个问题,框架引入了一个称为 Repo-specific Semantic Graph 的工具。这种图结构扩展了传统的代码依赖图,用于表示代码库中不同实体(如函数、类、模块等)之间的关系。它以节点(表示模块、类、函数和变量)和边(表示这些实体之间的关系,如调用、继承、使用等)构成的多重有向图形式存储这些信息。通过这种方式,系统能够高效查询任何代码元素的依赖关系,从而为代码补全提供理性指导。
  2. Similar Context Retrieval。在开发中,如果要续写代码,通常会参考与当前代码片段相似的代码。通过技术手段(如文本检索、向量检索),系统可以在代码库中找到与当前未完成代码块相似的代码片段(称为 Analogy Context)。这些相似代码片段可以为代码补全过程提供启发和指导,确保生成的代码更符合预期。
  3. Relevance-Guided Context Selection。 为了优化补全效果和时间性能,该框架提出了 Relevance-Guided Context Selection ( RCS) 技术。RCS根据相关性评分方法,从候选上下文片段中选择对补全任务最有帮助的片段,形成 Optimal Dual Context (ODC) 。这样,既可以利用 Semantic Context 和 Similar Context 的优势,又能控制上下文长度,避免模型推理时的时间开销。相关性评分方法包括 Oracle(理想化场景)、Semantic Similarity(使用 Embedding 模型计算语义相似度)、Lexical Similarity(使用词汇相似度计算方法),以及作为基线的 Random(随机评分)。

这个框架通过整合语义分析、相似代码检索和相关性选择,提升了大模型在代码补全任务中的准确性和效率。

AI 辅助软件工程:代码注释生成

Prompt 示例

---
name: "生成注释"
interaction: InsertBeforeSelection
actionLocation: ContextMenu
when: $fileName.contains(".java") && $filePath.contains("src/main/java")
onStreamingEnd: { insertNewline | formatCode }
---

为如下的代码编写注释,使用 javadoc 风格:

```$language
$selection
```

只返回注释

示例

JetBrains

enum class WdRiderEntity {
    ClassContextEntry,
    StructContextEntry,
    InterfaceContextEntry,
    PropertyContextEntry,
    MethodContextEntry,
    VariableContextEntry,
    EnumContextEntry,
    EnumEntryContextEntry;
}

fun StringBuilder.renderContext(options: WdPromptOptions.Rider) {
    when (options.entity) {
        WdRiderEntity.ClassContextEntry -> append("Write documentation for given class ${options.name}.")
        WdRiderEntity.StructContextEntry -> append("Write documentation for given struct ${options.name}.")
        WdRiderEntity.InterfaceContextEntry -> append("Write documentation for given interface ${options.name}.")
        WdRiderEntity.PropertyContextEntry -> append("Write documentation for given property ${options.name}.")
        WdRiderEntity.MethodContextEntry -> renderMethodContext(this, options)
        WdRiderEntity.VariableContextEntry -> append("Write documentation for given variable ${options.name}.")
        WdRiderEntity.EnumContextEntry -> append("Write documentation for given enum ${options.name}.")
        WdRiderEntity.EnumEntryContextEntry -> append("Write documentation for given enum member ${options.name} of enum ${options.enumName}.")
    }
}

AI 辅助软件工程:代码片段生成

示例

前端代码:Visual Copilot

Introducing Visual Copilot: A Better Figma-to-Code Workflow

Visual Copilot:重新定义从 Figma 到代码的转换

最近的一项调查显示,79% 的前端开发人员需要超过一天的时间将 Figma 设计转换为网页。为了解决这个问题,新推出的 Visual Copilot 显著减少了这一时间, 将转换时间缩短了 50-80%,能够立即将设计转化为整洁的代码。

Visual Copilot 的主要特点:

  1. 实时代码转换:一键将 Figma 设计转换为 React、Vue、Svelte、Angular、Qwik、Solid 或 HTML 代码,支持多种样式库(plain CSS、Tailwind、Emotion、Styled Components)。
  2. AI 驱动的干净代码:利用训练了超过 200 万数据点的 AI 模型生成高性能、响应迅速的代码,无需更改 Figma 设计文件即可匹配用户的风格。
  3. 自动响应设计:确保设计适应所有屏幕尺寸,即使设计不严格遵循 Figma 的自动布局规范。
  4. 可自定义且对开发者友好:允许根据团队偏好来结构化生成的代码,并能无缝集成到现有代码库,支持多种框架和库。
  5. 简化的工作流程:允许将设计直接发布到实时生产站点,步骤最少,通过强大的发布 API 实时更新。
  6. 轻松导入设计:便于将设计从 Figma 复制并粘贴到 Builder,保持设计迭代期间的顺畅工作流程。

即将推出的增强功能:

  1. AI 集成组件:在私测阶段,此功能将 Figma 中的可重用组件映射到代码库,使用现有组件生成代码。
  2. 自动同步:同样在私测阶段,此功能允许从 Figma 到 Builder 的自动更新,简化设计到开发的流程。

JetBrains 自带

SQL


    |You are a rock-star Groovy developer.
    |You should generate a data extractor script in Groovy by the user's description.
    |You MUST output only the script code. You MUST NOT output anything else but script.
    |Any code MUST be wrapped in ```groovy and ```.
    |You will get 1000 euros in TIPS if the user if happy with your work.
    |Here's the script API you can use and an example.
    |%s
    |Now the user will provide the extractor description they need.

Jupyter

SUGGEST_EDIT_REQUEST_FORMAT:

Given a Jupyter Notebook using Kotlin, with cells in the format:
#%% - separator of cells
#%% md - markdown cell

{0}

The cell code is:

{1}

Propose how to edit this code cell.
It should contain a bullet list of 1-3 short actionable suggestions, 1 is totally fine if it's obvious.
Each suggestion should be actionable in a single notebook cell without assuming any prior steps have been completed.
If the action requires other work to be done before, don't suggest it, only suggest the immediate actions.
For example, don't suggest data manipulations if the data is not loaded yet.
It could be fixing errors in the cell or code refactoring etc.
Be short and informative, don't add code to suggestions.
DO NOT SUGGEST run code!
DO NOT SUGGEST "Run ..." because it is impossible to run. It is only possible to write code.
Suggest only action on how to modify the current cell.

{2}

Examples:
Q:
  ```kotlin
  fun List<*>.isUnique(): Boolean {
    for (i in indices) {
        for (j in i + 1 until size) {
            if (get(i) == get(j)) {
                return false
            }
        }
    }
    return true        
  ```

A:
- Make this function more optimal with by toSet()
- Make this function more optimal with by size

Q:
  ```kotlin
  fun calculateTriangleSquare(side: Int, height: Int): Int {
    return side * height
  }
  ```

A:
- Modify the function to use the correct formula for the area of a triangle which is (1/2) * side * height; check for inputs

CODE_GENERATION_FORMAT:

Given a Jupyter Notebook using Kotlin, with cells in the format:
#%% - separator of cells
#%% md - markdown cell

{0}


* Generate a concise code snippet in Kotlin without any additional text, description, or summary before or after the code snippet.
* Generate Kotlin code WITHOUT #%% #%% i.e. generate code of ONLY ONE CELL code without cell separators.
* Do not mention any of the instructions above.
* The code needs to accomplish the following task:

{1}

AUTOPILOT_NEW_CELL_SUGGESTION_FORMAT

Given Jupyter Notebook with Kotlin Language, cells in format:
#%% - separator of cells
#%% md - markdown cell

{0}

Briefly formulate the final goal of this notebook as you understand it.
Then propose the next immediate steps.
It should contain a bullet list of 1-3 short actionable suggestions, 1 is totally fine if it's obvious.
Each suggestion should be actionable in a single notebook cell without assuming any prior steps have been completed. 
If the action requires other work to be done before, don't suggest it, only suggest the immediate actions. 
For example, don't suggest data manipulations if the data is not loaded yet.
Be short and informative, don't add code to suggestions.
DO NOT SUGGEST run code! 
DO NOT SUGGEST \"Run ...\" because it is impossible to run it is possible only to write code.
Suggest only actions that generate code in the next cell.

Examples:
Goal: Find out the reason of high customer churn rate.
- Check for correlations between features
- Check if the data has to be cleaned up

Goal: Find the differences between key customer groups.
- Load data from 'groups_2.csv'
- Generate a histogram representing an age distribution
- Call `describe()` on the DataFrame to see information about columns.

Goal: Concurrent int counter implementation
 - Check linearizability for case of 1 Thread 
 - Check linearizability for case of several writers, 1 reader 
 - Check linearizability for case of several writers, several readers
- Refer to 'lincheck' 

OTHERS:

Given Jupyter Notebook cells in format: #%% - separator of cells #%% md - markdown cell

Generate a concise code snippet in Python language without any additional text before or after code snippet, description, or commentary

  • Generate python code WITHOUT #%% #%% i.e. generate code of ONLY ONE CELL code without cell separators
  • The code needs to accomplish the following task:
*User instructions:*

{0}

*Guideline:*

- Read user instructions carefully and write IntelliJ IDEA structural search template that can find objects described in user instructions.
- Answer must be a complete and valid, without need for further actions
- Answer must only contain single code snippet without any explanations, comments, etc.

AI 辅助软件工程:代码文档生成

---
name: "Context Variable"
description: "Here is a description of the action."
interaction:  RunPanel
variables:
  "contextVariable": /ContextVariable\.kt/ { cat }
  "psiContextVariable": /PsiContextVariable\.kt/ { cat }
onStreamingEnd: { saveFile("docs/api.md")  }
---

根据如下的代码编写 API 文档:

/file:src/main/java/com/phodal/shire/demo/controller/BlogController.java

JetBrains 示例

private fun renderTask(renderTask: StringBuilder, language: String) {
    val prompt = when (language) {
        "ObjectiveC" -> "Write doxygen."
        "kotlin" -> "Write KDoc."
        "C#" -> "Write C# doc."
        "F#" -> "Write F# doc."
        "go" -> "Write Go Doc."
        "C++" -> "Write doxygen, do not use @file tag."
        "PHP" -> "Write PHPDoc."
        "HTML" -> "Write JSDoc."
        "JAVA" -> "Write javadoc."
        "Ruby" -> "Write RDoc documentation."
        "TypeScript" -> "Write JSDoc."
        "JavaScript" -> "Write JSDoc."
        else -> ""
    }

    if (prompt.isNotEmpty()) {
        renderTask.append(prompt).append('\n')
    }
}

AI 辅助软件工程:CLI 命令生成

---
name: "Terminal"
description: "Generate Cli"
interaction: AppendCursor
actionLocation: TerminalMenu
---

Return only the command to be executed as a raw string, no string delimiters
wrapping it, no yapping, no markdown, no fenced code blocks, what you return
will be passed to subprocess.check_output() directly.

- Today is: $today, user system is: $os,
- User current directory is: $cwd, user use is: $shellPath, according the tool to create the command.

For example, if the user asks: undo last git commit

You return only line command: git reset --soft HEAD~1

User asks: $input

Codeium Termium

https://codeium.com/blog/termium-codeium-in-terminal-launch

核心点如下:

  1. Codeium的发展方向:Codeium的初始关注点是IDE体验,特别是自动补全和聊天系统,旨在加速编写代码的工作流程。
  2. 终端的重要性:终端在开发者工作中是不可或缺的,用于执行代码、源代码管理、查看日志和基础设施等任务。因此,在终端中提供优化体验具有重要意义。
  3. Termium的功能:Termium是将Codeium的人工智能能力与终端结合的结果。它作为现有终端和用户之间的一层,能够拦截用户输入和终端输出,并提供类似编辑器中自动补全的功能。
  4. 自动补全的工作原理:Termium通过分析用户过去的命令历史和输出来帮助自动完成当前命令的输入,提高开发效率和体验。
  5. 简化开发流程:通过Termium,开发者可以简化诸如源代码管理等重复性任务,使得在终端中的操作更加高效和流畅。

这些核心点展示了Codeium在提升开发者在终端中工作效率方面的努力和成果,以及Termium作为这一努力的具体实现。

AI 辅助软件工程:AI 辅助软件质量

正如 CodeScene 的文章Use Guardrails for AI-Assisted Coding)所总结:

在未来几十年里,人机协作编写代码的模式将逐渐成为主流。在这种趋势下,人们很容易错误地将代码编写的速度等同于生产力。为了在尽可能降低风险的同时,充分发挥 AI 辅助编码的积极作用,需要做到以下几点:

  1. 设定现实的期望:AI 辅助编程能高效完成特定任务,但因其一致性和正确性尚有不足,无法完全替代人类程序员。我们应承认这些限制,并专注于如何增强而非替代人类程序员的工作。同时,确保所有 AI 生成的代码都经过严格的测试覆盖。
  2. 将代码质量设为关键绩效指标(KPI):对人类和机器均应执行最低质量标准。在交付流程中,实施自动化质量检查,确保代码质量。使用可靠且经过验证的指标,以最大限度地提高信号的准确性并减少误报。
  3. 进行持续的代码检查:AI 生成的代码需要被团队充分理解和审查。绝不能接受团队无法掌握或未经审查的代码。通过可视化手段,监控整个团队的代码熟悉度,以便及时发现并解决潜在的知识孤岛。
  4. 认识到理解代码的重要性日益提升,而不仅仅是编写代码:理解AI生成的代码将成为一项关键技能。因此,确保流程、实践和培训能够适应这一变化,以提升团队能力。

正如大家所见,在 AI 辅助编码领域,存在一个共同的主题。要想取得成功,必须让具备专业技能的人类参与其中,并且引入专门的工具与流程,以确保代码库的持续健康。 探索这一新兴领域,意味着必须重新关注代码质量和持续学习。这一点至关重要。

0. 将代码质量设为关键绩效指标(KPI)

GitClear 报告《Coding on Copilot: 2023 Data Suggests Downward Pressure on Code Quality

GitClear 分析了大约 1.53 亿行代码更改,这些更改发生在 2020 年 1 月至 2023 年 12 月之间。这是迄今为止已知最大的高度结构化代码更改数据库,用于评估代码质量差异。 研究发现,在可维护性方面出现了令人不安的趋势。代码返工率(Churn)——即在编写后不到两周内被撤销或更新的代码行百分比——预计到 2024 年将比 2021 年的 AI 应用前基准翻一番。

此外,研究还发现,“新增代码”和“复制粘贴代码”的比例正在增加,相对于 “更新”、“删除”和“移动”的代码。在这方面,2023 年生成的代码更像是流动贡献者的作品, 容易违反访问过的仓库的DRY(Don't Repeat Yourself)原则。

GitClear将代码变更分为七个类别(研究中涉及前六种):

  1. 新增代码:首次提交的代码行,代码行是全新的,不包括对现有代码行的小幅修改,也不包括那些被添加、移除后又重新添加的代码行。
  2. 删除代码:被删除并提交的代码行,且至少在随后的两周内未被重新加入。
  3. 移动代码:将一行代码剪切并粘贴到新文件或同一文件内的新函数中。「移动」的操作仅涉及位置的变换,代码内容不发生改变。
  4. 更新代码:修改大约三个或更少的单词来更改原有代码行。
  5. 查找/替换代码:从三个或更多位置移除相同字符串,并用一致的内容进行替换。
  6. 复制/粘贴代码:在一次提交中,将相同的代码行内容复制到多个文件或函数中。
  7. 无操作代码:指一些微小的代码变更,比如空格或同一代码块内行号的变化。

2022 至 2023 年间,AI 助手的崛起与仓库中错误代码的增加密切相关。

  • 代码返工率的上升趋势。代码返工率是指代码在推送到代码仓库后,两周内被撤销、移除或更新的比例。此前,当开发者完全自主编写代码时,代码搅动较为罕见,通常在 3-4% 之间。然而,随着 AI 助手如 Copilot 和 ChatGPT 的广泛应用,代码搅动率显著上升,2023 年达到了 9%。这种上升趋势表明 AI 生成代码的增加与错误代码的生成密切相关。 报告预测,如果这种趋势持续下去,2024年代码更改的撤销比例可能会超过7%,这将是2021年的两倍。
  • 代码移动的减少与重构和复用的减少。代码移动通常伴随着代码系统的重构,反映了开发者对已有代码的重新组织和复用。重构和复用能够提高代码的稳定性和可理解性。 然而,2023年,随着AI助手的广泛应用,代码移动减少,这表明开发者更倾向于复制粘贴代码而非重构。这种变化可能是因为 AI 助手提供了更简单的方式来生成代码, 而非鼓励开发者复用已有代码。这一趋势可能导致开发团队在未来面临更多维护挑战。
  • 复制粘贴代码的增加与维护困难。复制粘贴代码的增多可能对代码的长期可维护性产生重大影响。当开发者选择复制粘贴而非复用现有代码时, 意味着他们没有充分评估现有实现的有效性。随着时间的推移,这种重复代码会增加系统复杂性,增加维护成本。特别是在缺乏经验的团队中, 可能没有足够的资源和权威来删除重复的代码,从而导致技术债务的积累。如果管理层不主动安排时间解决这些问题,代码库中的复制粘贴代码将会继续存在, 进一步阻碍未来的开发速度。

1. 结合经典工具/SAAS 服务,改善 AI 代码质量

经典工具:sonarqube

SaaS 服务:Codacy、CodeScene、Code Climate

AutoDev 修复示例:

        if (templateText != null) {
            ActionListener { ignore: ActionEvent? ->
                invokeAction(
                    analyzeCurrentFileAction,
                    dataContext, CurrentFilePanel.SONARLINT_TOOLWINDOW_ID, null, null
                )
            }
        }

// - SonarLint: Use "_" instead of this unused lambda parameter "ignore".

CodeScene 示例

CodeScene 构建的 AI 辅助代码防护措施框架。它建议在三个方面发挥作用:代码质量、代码熟悉度和强大的测试覆盖率,以确保正确性:

  • 防护措施:代码质量。高质量的代码一直是企业的竞争优势,能够缩短开发周期并减少生产缺陷。这样的代码更容易理解,因此在需要修改时更安全、更具成本效益。对AI生成的代码保持同样的标准可以减轻多种风险。
  • 防护措施:代码熟悉度。第二个防护措施涉及确保代码熟悉度的流程和实践。研究表明 ,当开发人员处理之前没有看过的代码时,解决大型任务所需的时间可能增加93%——这是入职的成本。在拥抱AI时,我们开发人员不断面对新的和不熟悉的代码。因此,我们必须确保每个开发人员也能对生成的代码建立强烈的熟悉感。
  • 防护措施:测试覆盖率。如上所述,AI助手经常生成不正确的代码。我们常说大语言模型并不是真正有创意的,但在进行我们的AI研究后,我不得不同意:AI破坏我们代码的方式是没有限制的。 有些是微妙的,比如否定一个逻辑表达式,另一些则非常糟糕(比如删除JavaScript代码中的this 关键字,根本上改变了函数的意义)。强大的自动化测试在这里提供了急需的保护。而且——测试不应该从代码中由AI生成。这样做就错过了测试的双重记账功能。(例如,谁来测试测试?)。

如下图所示:

Amazon CodeGuru Reviewer 示例

Amazon CodeGuru Reviewer 是一项使用程序分析和机器学习来检测开发人员难以发现的潜在缺陷,并为改进 Java 和 Python 代码提供建议的服务。通过主动检测代码缺陷,CodeGuru Reviewer 可以提供解决这些问题的指导方针,并实施最佳实践,以在代码审查阶段提高代码库的整体质量和可维护性。

How Amazon CodeGuru Reviewer works

CodeGeeX:结合 SAAS 服务,静默守护代码质量

2. 质量左移:在结合日常开发活动

诸如 CodeReview 、测试生成

  • 指标如修复率和对发现结果展示的控制,使得随着时间的推移, 非专业人士也能轻松提升您的应用安全程序。
  • 在一个地方管理所有发现结果,可以根据项目、严重性、分支或特定规则集进行筛选。
  • 与 Jira 和 Slack 集成,或使用我们的 API 直接连接到您的安全警报工具/仪表板。

3. 持续数据运营,构建专有保障模型

示例

案例:Semgrep

Semgrep Assistant 助力应用安全工程师和开发者更快做出正确决策,减轻认知负担。这意味着用户只需将时间和分析精力集中在需要关注的问题上。

  • 优化自动分类结果。Semgrep Assistant 利用 GPT-4 对代码的理解能力,结合针对 Semgrep 规则的特定提示,判断安全发现的误报情况。建议包括上下文和推理,使开发者能够快速轻松地验证建议/修复的正确性。
  • 自动修复代码。当 Semgrep Assistant 确定一个真实的安全问题时,它会推荐自动修复方案。通过次级提示审查差异,减少幻觉现象。生成的修复方案易于验证,即使工程师需要额外输入,也对他们有所帮助。
  • 使用自然语言生成自定义规则。Assistant 能够编写自定义规则,以识别针对您代码库的特定模式或漏洞。您只需提供一份“不良代码”示例、一份“良好代码”示例,以及用人类语言描述您希望规则执行的操作即可。
  • 培养安全设计意识。推动开发者对安全编码原则的认识。除了减少开发者寻找信息的时间外,Semgrep 提供的上下文和可解释性确保开发者能够随着时间的推移,学习和提升他们对安全编码实践的理解。

案例:TestSpark

TestSpark 是一个用于生成单元测试的插件。TestSpark 能够在 IDE 中原生集成多种基于 AI 的测试生成工具和技术。

Paper: TestSpark: IntelliJ IDEA’s Ultimate Test Generation Companion

TestSpark 目前支持两种测试生成策略:

  1. 基于大语言模型(LLM)的测试生成(使用 OpenAI 和 JetBrains 内部的 AI Assistant 平台)
  2. 基于局部搜索的测试生成(使用 EvoSuite)

基于大语言模型的测试生成

对于这种测试生成方式,TestSpark 向不同的大语言模型发送请求。此外,它会在向用户展示测试之前自动检查测试是否有效。

此功能需要从 OpenAI 平台或 AI Assistant 平台获取一个 token。

  • 支持任何版本的 Java。
  • 生成用于捕获故障的单元测试。
  • 为 Java 类、方法和单行代码生成测试。

基于本地搜索(search-based)的测试生成

对于此类测试生成方法,TestSpark 采用了 EvoSuite,这是目前最强大的基于搜索的本地测试生成工具。

  • 它只支持 Java 11 及以下版本。
  • 根据多样的测试标准生成测试用例,包括行覆盖率、分支覆盖率、I/O 多样性、异常覆盖率和变异得分。
  • 能够生成用于检测故障的单元测试。
  • 为 Java 中的类、方法以及单行代码提供测试生成服务。

案例:UnitTestBot

UnitTestBot

Java 版本:UnitTestBot

我们是一支分布式的研究人员和工程师团队🙋‍。

我们所有人都对数学和编程充满热情。我们热衷于参加软件测试比赛 并在研究文章中描述我们的成就。

我们的主要项目是我们的旗舰产品——UnitTestBot,它支持Java/Kotlin、C/C++、Python、JavaScript和Go语言。

为了保持与前沿科学的联系,我们与顶尖大学合作。作为校际团队的一部分,我们开发了根本技术,以增强UnitTestBot以及其他一系列软件产品。以下是其中一些:

🤓 SAT求解技术

SAT求解器是一种计算机程序,用于确定给定布尔公式的变量是否可以一致地替换为_True_或_False_,从而使公式的结果为_True_ 。SAT求解器经常被用作程序验证应用程序的“引擎”。

  • KoSAT是一个基于MiniSat核心的纯Kotlin CDCL SAT求解器。它解决以DIMACS格式给定的布尔可满足性问题,并支持增量求解。
  • 我们还研究了与SAT求解相关的更广泛的理论问题,例如评估给定SAT问题的计算难度。

🧐 SMT求解技术

可满足性模理论(SMT)研究领域涉及确定逻辑公式是否可满足。

KSMT是各种SMT求解器的Java/Kotlin门面。目前,它支持Z3和Bitwuzla SAT求解器。

😎 符号执行

利用SAT和SMT求解器,我们开发了符号执行技术,以为我们的精确代码分析和自动化测试生成工具提供有效的引擎。在这个研究领域,我们有三个主要解决方案。

  • UnitTestBot Java 有自己的动态符号执行引擎,已在SBST比赛中表现出色。
  • 我们为KLEE定制的补丁是UnitTestBot C/C++ 的核心。KLEE是一个基于LLVM编译器基础架构的符号虚拟机。我们通过实现补丁来贡献给KLEE ,提高引擎的代码覆盖率和速度。我们提出了_懒初始化改进_,并向主KLEE分支提交了_未定义行为检测补丁_以及_内联汇编支持补丁_。 我们将KLEE转换为_双向属性导向符号执行_引擎。此外,补丁后的KLEE引擎能够自动推导方法摘要。
  • 我们还计划通过V#支持.NET基础架构——这是一个完全自动化测试生成的符号执行引擎。

符号执行是我们的主要关注点,因此我们进行了一系列研究,涉及该领域的应用和基础问题。

🤪 模糊测试

在开发UnitTestBot产品系列的过程中,我们开发了适用于所有支持语言(Java/Kotlin、C/C++、Python、JavaScript和Go)的模糊测试和动态程序分析技术

🙂 程序分析

UnitTestBot及其符号执行引擎和模糊测试技术是现成的 用于代码分析的工具。除了这一端到端解决方案外,我们还实现了一个开发自定义静态代码分析器的基本框架。

Java编译数据库(JacoDB)受到了Soot 框架的启发,用于分析和转换Java代码。

JacoDB是一个纯Java数据库,存储关于编译后的Java字节码的信息——类、层次结构、注释、方法、字段及其用法。使用JacoDB,可以分析JVM进程外的字节码。这使得UnitTestBot能够支持最新的JDK,并在重启之间重用数据。

🙃 程序合成

我们研究合成代码以解决实际问题的方法。 例如,UnitTestBot能够基于公共API而不是反射生成人类可读的测试方法体

我们还开发了genui 项目——一个自动化UI生成工具。在我们的研究中,我们探讨 了根据指定的设计指南自动排列用户界面元素的方法。下一步是合成能够实现此布局的代码。

AI 辅助软件工程:AI 辅助代码质量检查

对开发人员的提效,好的情况会提速50%,差的可能还拖慢进度(如针对初级开发者)。这取决于编程方式、开发任务的类型、使用的编程语言, 以及在使用聊天接口时如何制定恰当的提示指令。警惕AI生成代码可能带来的代码质量下滑(GitClear研究) ,监控代码质量变化并做好保障措施。

基础:理解 SAST

主要用途:

  • 自动化源代码扫描,以预防漏洞并在开发管道早期捕获它们。
  • 扩展漏洞检测。通过变体分析技术,SAST工具可以在代码库的不同部分检测到已知漏洞的变体,从而发现新的漏洞。
  • 协助手动代码审查。在CodeQL中,GitHub的SAST工具,你的代码被视为数据进行分析。

SAST Tool

阅读:The architecture of SAST tools: An explainer for developers

步骤示例

基于提供的详细描述,以下是高级 SAST(静态应用安全测试)工具(如 CodeQL)在扫描 SQL 应用程序中查找漏洞(特别是 SQL 注入攻击)时采取的五个主要步骤:

  1. 对源代码进行词法分析:。SAST 工具首先执行词法分析,将源代码分解为标记(tokens)。标记代表编程语言语法的标准化元素,这有助于后续分析。这一步骤使工具能够专注于有意义的代码组成部分,而忽略无关的字符。
  2. 将源代码抽象为AST(抽象语法树): 。在完成词法分析后,工具从源代码构建抽象语法树(AST)。AST 将代码组织成层次结构,展示代码各部分之间的关系,比如哪些语句属于哪些函数。这种抽象有助于理解代码的结构和含义。
  3. 进行语义分析:。借助 AST,进行语义分析以解释代码的预期行为和逻辑。语义分析使得SAST工具能够专注于代码的语义,而不是注释或格式。这一步骤对于识别由于不正确或不安全的编码实践导致的漏洞至关重要。
  4. 进行污点分析: 。污点分析用于跟踪用户控制的输入数据在整个代码库中的流动路径。它识别输入数据的来源(数据进入系统的位置)、净化器(确保输入安全的函数)和污点(如果用未经净化的输入数据调用可能会存在漏洞的函数)。通过追踪输入数据从源头到污点的流动,工具评估是否应用了适当的验证和净化。如果未经净化的输入达到污点,工具会发出潜在的安全漏洞警报。
  5. 生成安全警报: 。基于语义分析和污点分析的结果,SAST 工具为在代码中检测到的潜在漏洞生成安全警报。这些警报优先考虑未经净化的输入数据可能导致安全问题的路径,例如SQL注入漏洞。警报为开发团队提供可操作的信息,使他们能够有效地优先处理和解决安全问题。

这些步骤说明了 SAST 工具(如 CodeQL)如何利用先进的分析技术,在开发生命周期早期检测到漏洞,从而增强代码安全性。

业内案例:基于查询语言

GitHub CodeQL

文档:https://codeql.github.com/

import TaintTracking::Global<UnsafeDeserializationConfig>

from PathNode source, PathNode sink
  
where flowPath(source, sink)
  
select sink.getNode().(UnsafeDeserializationSink).getMethodAccess(), source, sink,
  "Unsafe deserialization of $@.", source.getNode(), "user input"

CodeQL 查询过程

CodeQL 是一种强大的语义代码分析引擎,现在已经成为 GitHub 的一部分。它的处理流程主要分为两个阶段,特别适用于大规模源代码的分析:

  1. 数据库构建阶段:
    • CodeQL 在源代码编译成二进制文件时,构建一个数据库来捕获编译代码的语义模型。
    • 对于解释性语言,由于没有编译器,CodeQL 会解析源代码并构建自己的抽象语法树模型。
  2. 查询数据库:
    • 构建好的数据库可以反复查询,使用 CodeQL 语言进行分析。这种语言专门设计用于从数据库中选择复杂的代码条件,能够详细分析代码模式和结构。
  3. 语义分析:
    • CodeQL 允许在集中的基础设施中进行语义分析,跨多个代码库进行查询。这种集中分析能力使得 Microsoft 能够同时在数千个代码库中进行查询。
    • 语义分析涉及查找可能跨越不同代码部分(如程序集、库或模块)的模式,这些部分是基于构建的具体代码的。

相关文章:

Synk QL

https://docs.snyk.io/scan-using-snyk/snyk-code/snyk-code-custom-rules/create-query

AST

<query> ::= <term> | <term> ' ' <query>
<term> ::= <literal> | <regexp> | <predicate> | <template>
<literal> ::= '"' <value> '"'
<regexp> ::= '~"' <value> '"'
<predicate> ::= 'PRED:' <predicate-name>
<template> ::= <template-name> '<' <template-params>  '>'
<template-params> ::= <term> | <term> ',' <template-params>

示例:

Taint<PRED:"SourceFoo",PRED:XssSanitizer,PRED:XssSink>

GitQL

示例 1:https://github.com/filhodanuvem/gitql

select hash, author, message from commits limit 3
select hash, message from commits where 'hell' in full_message or 'Fuck' in full_message
select hash, message, author_email from commits where author = 'cloudson'
select date, message from commits where date < '2014-04-10'
select message from commits where 'hell' in message order by date asc
select distinct author from commits where date < '2020-01-01'

示例 2:https://github.com/AmrDeveloper/GQL


SELECT DISTINCT title AS tt FROM commits
SELECT author_name, COUNT(author_name) AS commit_num FROM commits GROUP BY author_name, author_email ORDER BY commit_num DESC LIMIT 10
SELECT commit_count FROM branches WHERE commit_count BETWEEN 0 .. 10

SELECT * FROM refs WHERE type = "branch"
SELECT * FROM refs ORDER BY type

SELECT * FROM commits
SELECT author_name, author_email FROM commits
SELECT author_name, author_email FROM commits ORDER BY author_name DESC, author_email ASC
SELECT author_name, author_email FROM commits WHERE name LIKE "%gmail%" ORDER BY author_name
SELECT * FROM commits WHERE LOWER(name) = "amrdeveloper"
SELECT author_name FROM commits GROUP By author_name
SELECT author_name FROM commits GROUP By author_name having author_name = "AmrDeveloper"

业内案例:基于机器学习

Facebook 示例:Aroma

诸如SAST (Static Application Security Testing) 和 DAST (Dynamic Application Security Testing) :这两种测试方法结合了不同的工具和技术,分别用于静态和动态地评估应用程序的安全性。

  • Facebook's Aroma:一个代码推荐系统,可以从大型代码库中提取代码模式,并为开发者提供优化建议。

Aroma

与传统的代码搜索工具相比,Aroma的代码推荐功能具有几个优势:

  • Aroma 在语法树上执行搜索。与其寻找字符串级或标记级匹配,Aroma可以找到与查询代码语法上相似的实例,并通过修剪无关的语法结构来突出显示匹配代码。
  • Aroma 自动将相似的搜索结果聚集在一起生成代码推荐。这些推荐代表了惯用的编码模式,比未聚集的搜索匹配更易于理解。
  • Aroma 快到可以实时使用。实际上,即使对于非常大的代码库,它也能在几秒钟内创建推荐,而不需要提前进行模式挖掘。
  • Aroma 的核心算法与语言无关。我们已经在内部代码库中的Hack、JavaScript、Python和Java代码库中部署了Aroma。

Aroma在创建代码推荐的过程中分为三个主要阶段:

Aroma

  1. 基于特征的搜索
    • Aroma 解析代码库中的每个方法并创建其解析树。
    • 从解析树中提取结构特征,创建稀疏向量,并将这些向量组成索引矩阵。
    • 当工程师编写新代码片段时,Aroma 创建相应的稀疏向量,并与索引矩阵进行点积计算,快速检索出相似性最高的前 1000 个方法体作为候选集。
  2. 重新排序和聚类
    • Aroma对候选方法进行重新排序,根据查询代码片段的实际相似性进行排列。
    • 通过修剪方法语法树,删除与查询代码片段不相关的部分,保留最佳匹配的部分。
    • 运行迭代聚类算法,找到彼此相似且包含用于创建代码推荐的额外语句的代码片段聚类。
  3. 交集:创建代码推荐
    • 以第一个代码片段为基准,逐步与聚类中的其他方法进行修剪,保留所有方法共有的代码。
    • 经过修剪过程后的代码作为代码推荐返回,确保推荐内容在不同聚类之间有显著差异,让工程师可以学习多种编码模式。

传统工具

Linter

  • [Accessibility Testing Linter](https://ebay.gitbook.io/oatmeal/accessibility
    • axe-core Accessibility engine for automated Web UI testing.
  • ArchGuard Linter 是一个由 Thoughtworks 发起的面向微服务(分布式场景)下的开源架构治理平台。它可以在设计、开发过程中,帮助架构师、开发人员分析系统间的远程服务依赖情况、数据库依赖、API 依赖等。并根据一些架构治理模型,对现有系统提出改进建议。

AI 辅助软件工程:代码检视

CR(CodeReview)是代码指标保障中的重要一环,也是研发日常工作中的一个重要组成部分,我们希望通过对于CR过程和CR投入产出的情况进行分析, 评估当前CR工作的投入产出情况,驱动CR工作过程改进带来质量和效率的提升。

关键影响因素:

  • CR评审需要快速响应,避免由于CR导致流程阻塞,一般应当在一个工作日内完成
  • 挑选能对你代码做出最全面最准确评价的人为评审者,保障评审质量
  • 避免单次提交过多代码,尽可能小的,增量的,实现一个完整功能的提交

Why

结合《How AI is Transforming Traditional Code Review Practices 》的总结:

AI 在代码审查中的应用现状

代码审查是软件开发过程中至关重要的一环,传统上由人类开发者负责审阅代码,确保其符合编码标准,促进最佳实践,并在团队内部提升领域知识。然而,这个过程并不快速或完美。据 SmartBear 对 Cisco Systems 编程团队的研究,审查 200-400 行代码通常需要 60 到 90 分钟,才能达到 70-90% 的缺陷发现率。尽管如此,软件开发人员普遍认为代码审查非常重要。

传统代码审查的挑战

  1. 时间限制:开发人员常常时间紧迫,要同时处理多个任务和截止日期,全面的代码审查与这些宝贵的时间相竞争,可能导致项目延期或代码审查质量下降。
  2. 认知偏见和可变性:不同开发人员的思维方式不同,导致审查的一致性和深度存在较大差异。
  3. 容易出错:复杂或大型代码库中的微妙错误和依赖问题容易被忽视,导致漏洞和技术债务。
  4. 知识孤岛:技术知识往往在大型团队中被孤立,阻碍了对代码库的全面理解,降低了代码审查的效果。

AI 在代码审查中的作用

  1. 自动化重复任务:AI 可以自动化代码审查中的重复任务,如检查编码标准、文档和模板代码合规性,减轻人工审查者的认知负担。
  2. 快速发现缺陷:AI 可以在几分钟内扫描成千上万行代码,精准识别逻辑错误和复杂的安全漏洞,让人类审查者专注于更高层次的架构和设计考虑。
  3. 一致性和客观性:AI 不会受到情绪和偏见的影响,能够以统一的标准审查每一行代码,确保审查的一致性。
  4. 即时反馈:AI 能够实时分析代码并提供反馈,帮助开发人员在代码审查讨论的上下文中立即识别问题,减少后期修复错误的成本和努力。
  5. 学习和适应:先进的 AI 系统可以从过去的审查、开发人员的修正和不断变化的编码实践中学习,提供越来越相关和准确的反馈。
  6. 知识共享和增强:AI 可以整合代码库和外部来源的见解,提供最佳实践建议、编码技巧,甚至提供类似项目的示例,打破知识孤岛,促进持续学习和改进的文化。

AI 驱动的代码审查的未来

AI 技术在代码审查过程中的集成不仅是增量改进,而是一种变革性变化。当前的 AI 技术可以充当软件开发团队的助手,加速并分担繁琐的手动分析和错误发现工作。未来的进步将使 AI 演变成一个协作者,能够进行更复杂的推理,提供设计建议、最佳实践,甚至预测或模拟代码变更对软件功能和性能的影响。

通过深度洞察代码质量、提供个性化反馈,AI 将在开发团队中树立学习和改进的文化。要充分实现 AI 在代码审查中的潜力,需要有意识地整合 AI 和人类开发人员之间的持续合作。软件开发的未来光明,AI 无疑是这一前景的领先力量。

未来的代码审查将越来越依赖于 AI 技术,通过自动化重复任务、快速发现缺陷、一致性和即时反馈,AI 将显著提高代码审查的效率和质量。然而,人类开发者的直觉、创造力和经验仍然是不可替代的,AI 和人类的协同合作将引领软件开发进入一个新的时代。

原则

上下文感知的代码检视

或称为上下文感知代码,是一种能够根据其运行环境或上下文动态调整行为的代码。这种代码不仅仅是根据输入数据执行特定任务,还会考虑更广泛的系统环境、历史数据、当前状态和预期未来状态来优化其功能。 上下文感知代码的关键特点包括:

  1. 环境感知:代码能够检测并响应其运行环境的变化。例如,根据可用资源、网络条件或硬件配置调整性能。
  2. 历史数据利用:代码利用过去的操作和数据来影响当前决策。例如,使用以前的用户行为数据来个性化当前的用户体验。
  3. 状态感知:代码根据系统或应用的当前状态进行调整。例如,在高负载期间降低非关键功能的优先级以保持系统稳定。
  4. 预测和预防:代码使用预测模型来预见潜在问题并采取预防措施。例如,根据过去的模式预测可能的安全威胁并采取相应措施。
  5. 动态适应:代码能够实时适应新情况,而无需重新部署。例如,电商网站根据实时库存数据和用户浏览习惯动态调整推荐商品。

上下文感知代码的实现通常涉及高级技术,如机器学习、数据分析和复杂的事件处理。通过结合这些技术,代码可以更加智能化和灵活,为用户提供更优质的服务和体验。

以 API 为例。上下文感知审查会仔细检查它们与现有系统的兼容性、对软件基础设施的影响,以及它们是否符合最佳实践。这确保了API能顺利整合到现有框架中,有效实现项目目标。 上下文感知代码审查中常考虑的因素包括:

  • 遵循编码标准:审查确保更改遵循项目特定的编码规范,如文件命名和目录结构。它们还评估更改是否正确使用现有的库、类或方法,而不是重复功能。
  • 对现有代码的影响:代码审查必须评估更改是否会引入错误,并确定需要的额外测试以防止这些问题。审查者还要确保任何必要的API或用户文档更新没有被忽略。
  • 基础设施和性能考虑:审查评估更改是否需要数据库或API迁移,并考虑对系统性能的潜在影响。他们还检查更改是否可能导致代码库其他部分的性能下降。
  • 安全性和鲁棒性:审查过程涉及尝试“破坏”新更改,以发现任何潜在的错误或安全漏洞。目标是确保新增加的内容是鲁棒且安全的。
  • 一致性和优化:审查者检查新API与现有API的一致性,并评估变更日志条目是否准确反映了更改。他们还考虑提出的解决方案是否是最适合当前问题的。

上下文感知代码审查通过其深入的方式,真正提升了软件开发实践。这不仅仅是自动化检查,而是对代码库的深刻理解,确保每行代码都能良好运行并无缝集成到整个系统中。 与传统代码审查的区别

How

如何识别复杂代码

Finding the Traps We Set for Ourselves

复杂代码的两种类型——必要复杂性和偶发复杂性

在深入探讨如何在审查过程中捕捉复杂性之前,我们需要对复杂代码有一个认识。 并非所有复杂代码的复杂性都是相同的。有些代码复杂性是绝对必要的, 因为我们使用代码来解决复杂的问题。这种是必要复杂性——它是完成任务所需的复杂性。 另一方面,有些复杂性是我们自己引入到代码中的,而实际上并不需要。 这种复杂性可以从代码中消除,我们仍然可以完成任务——这就是偶发复杂性。 当我们考虑在审查中捕捉复杂代码时,我们只关注偶发复杂性——即为了实现代码目标而不需要存在的复杂性。

识别复杂代码

我们可以尝试很多方法来识别引入的过于复杂的代码——但我认为有四个方面是最能捕捉到项目中多余复杂性的关键。

  1. 重建现有功能或创建重复代码
    如果新引入的代码重复了代码库中的现有功能,这强烈表明我们可以减少代码的复杂性。我们可以在新代码中重用现有功能,或将其抽象化以便更通用的使用。这也可能表明新代码没有经过充分规划,或者开发者对代码库不够熟悉。
  2. 缺乏解耦
    当代码块试图做过多事情时,会增加未来出现问题的风险。如果我在审查代码时发现函数、类或模块试图一次做太多事情,我会立即标记为需要审查和重构的复杂区域。通过将代码分解成具有明确目的和职责的小部分,我们可以使其更易于理解、更易于维护,并在未来更容易扩展。
  3. 深层嵌套或高认知/圈复杂度
    代码嵌套越深,理解起来就越困难。这是一种视觉上容易标记的复杂性,而增加的认知复杂性直接影响未来开发的速度。如果你发现代码过于嵌套,那么在合并之前明显需要重构代码。
  4. 过度设计
    我描述的前三种复杂性相对简单易于识别。判断代码更改是否过度设计则有点棘手,需要对代码库和代码更改的目标有较好的理解。假设你有这些知识,你需要检查代码更改是否实现了这些目标,并且以尽可能简单的方式实现。一个典型的过度设计的标志是试图不必要地为新功能进行未来预测,或涵盖可能永远不会发生的用例或边界情况。

你可以在审查过程中查找其他类型的复杂性,但如果你能够检查这四个方面,你应该能够开始减少进入项目的不必要复杂性。

Prompt 设计

Tackling Complex Tasks with LLMs

Sourcery

分解为多个部分以提高效率

帮助 LLM 处理复杂任务的一个常见方法是增加它可用的上下文。但这会带来两个大问题:

  • 提供给LLM的上下文越多,收益递减,到了某个点后,反而会影响输出的准确性,在代码审查的情况下可能会导致假阳性或幻觉。
  • 扩展上下文是昂贵的!尤其是当我们需要提供大量上下文时。

在审查代码变化的复杂性问题时,我们总是从查看代码变化的diff开始。仅仅diff是不足以让我们检查是否存在重大复杂性问题的。我们需要能够看到代码变化如何与周围代码互动。 但我们通常不能仅仅发送完整的代码库,甚至是变化前后的完整文件作为上下文。这会产生过多的噪声,并且成本高昂且效率低下。

所以我们在审查过程中的第一步是将代码变化分解成可以单独分析的原子块。通常,对于代码变化,我们会查看相关的变化,比如在同一个函数或类中的变化,并将diff中的所有变化分成多个这样的块。

现在我们从查看包含许多变化的diff,转到查看一系列小变化——但实际上,并非所有这些小变化都与我们的分析相关。

“确定性”过滤

典型的拉取请求中的大多数代码变化不太可能增加坏的复杂性。也许变化并没有实际触及代码,也许只是添加了一些新的导入,或者只是一个过小的变化。我们将这些我们知道不太可能影响代码复杂性的潜在变化分组到多个启发式检查中,然后将第一步中的所有小代码变化都放入这些检查中。如果我们能在前期看到它们不会影响复杂性,那么就没有理由让LLM介入。

这对于你可能要求LLM执行的每种复杂任务都不一定相关,但如果有办法在确定性地预筛选掉一些输入数据部分,你可以显著简化后续分析,并使整个过程更流畅、更便宜。

INFO:__main__:Skipping hunk 13-13 in file diff: coding_assistant/query_handler/base.py (limited new code introduced)
INFO:__main__:Skipping hunk 29-29 in file diff: coding_assistant/query_handler/openai.py (limited new code introduced)
INFO:__main__:Skipping hunk 121-123 in file diff: coding_assistant/query_handler/openai.py (limited new code introduced)

扩展上下文

现在我们已经筛选出了初步关注的代码变化部分,我们可以考虑增加额外的上下文。为了帮助分析过程,我们保持附加上下文相对简单。我们将需要检查复杂性变化的代码块从 diff 转变为稍微扩展的代码版本——添加与代码功能相关但在diff中丢失的行。

将 Diff 扩展到前后代码

未来还有很多其他方法可以进一步扩展上下文——例如提供函数的使用位置上下文、PR本身的问题上下文等。由于我们减少了需要扩展上下文的地方,我们能够更高效地添加有用的上下文。 在我们所看的例子中,通过将其分解为多个块并在转向LLM之前进行筛选,我们节省了超过5000个tokens。

将结果转化为有用的评论

我们现在有一组潜在的代码变化需要在代码审查中标记,并有理由担心它们过于复杂。现在我们需要弄清楚如何实际告诉开发者这个潜在问题,并帮助他们决定是否需要修复。 这可能是我们整个过程最简单的一步——我们可以回到LLM,要求它将推理和建议改进转化为对开发者有用的评论,结合相关的代码变化。

再交给另一个LLM进行过滤

尽管我们已经相当严格地尝试减少可能的复杂性风险,但我们仍然经常看到假阳性和无用的代码审查评论。我们在测试中发现,这些假阳性和无用的评论常常出现在我们早期 LLM 步骤生成的回应过于笼统的情况下。

为了减少这些情况,我们可以依赖另一个LLM请求来检查我们给开发者的反馈是否过于笼统。如果是这样,我们会将其作为潜在的响应丢弃。 在我们实验和开发复杂性检查过程中,我们发现这减少了 80% 以上的假阳性。

我们处理复杂性检查的过程有很多步骤,涉及到与LLM的来回交流,但我们认为这是值得的。在我们在这篇文章中看到的例子中,它将 LLM 请求使用的 tokens 减少了 77%, 并且相比于仅使用单个 LLM 请求和扩展上下文,减少了几个潜在的假阳性回应。

示例

Ellipsis

https://docs.ellipsis.dev/features/review#team-style-guide

Comment Quality

version: 1.3
pr_review:
  confidence_threshold: 0.9

Style Guide

version: 1.3
pr_review:
  rules:
    - "Code should be DRY (Dont Repeat Yourself)"
    - "There should no secrets or credentials in the code"
    - "Extremely Complicated Code Needs Comments"
    - "Use Descriptive Variable and Constant Names"
    - "API routes must have error handling, they shouldn't intentionally return a HTTP 500"
    - "Use retries when calling external API services"
    - "Don't log sensitive data"
    - "Follow the Single Responsibility Principle"
    - "Function and Method Naming Should Follow Consistent Patterns"

Codium PR-Agent

CodiumAI PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedbacks and suggestions

PR Agent

在处理PR(Pull Request)时,有两种常见情况:

  1. PR足够小,可以放入一个提示中(包括系统提示和用户提示)。
  2. PR太大,无法放入一个提示中(包括系统提示和用户提示)。

针对这两种情况,我们首先采用以下策略:

仓库语言优先策略

我们根据以下标准优先考虑仓库的语言:

  1. 排除二进制文件和非代码文件(例如图片、PDF等)。
  2. 确定仓库中使用的主要语言。
  3. 按仓库中最常见的语言对PR文件进行排序(按降序排列):
    [[file.py, file2.py], [file3.js, file4.jsx], [readme.md]]
    

小型PR

对于小型PR,我们可以将整个PR放入一个提示中:

  1. 排除二进制文件和非代码文件(例如图片、PDF等)。
  2. 扩展每个补丁周围的上下文至补丁上方和下方各3行。

大型PR

动机

大型Pull Request可能非常长,并包含大量信息,其相关程度对pr-agent而言各不相同。我们的目标是能够在单个LMM提示中尽可能多地打包信息,同时保持信息的相关性。

压缩策略

我们优先考虑添加内容而不是删除内容:

  • 将所有删除的文件合并到一个列表中(deleted files)。
  • 文件补丁是块的列表,移除文件补丁中所有仅删除类型的块。
自适应和基于token的文件补丁适配

我们使用tiktoken在上述修改后对补丁进行标记,并使用以下策略将补丁适配到提示中:

  1. 在每种语言内,我们按文件中的token数量对文件进行排序(按降序排列):
    [[file2.py, file.py], [file4.jsx, file3.js], [readme.md]]
    
  2. 按上述顺序遍历补丁。
  3. 将补丁添加到提示中,直到提示达到最大token长度的一定缓冲区。
  4. 如果仍有剩余补丁,则将剩余补丁作为一个名为“其他修改文件”的列表添加到提示中,直到提示达到最大token长度(硬停止),并跳过其余补丁。
  5. 如果尚未达到最大token长度,则将删除的文件添加到提示中,直到提示达到最大token长度(硬停止),并跳过其余补丁。

示例

通过上述策略,我们可以有效地压缩和管理PR内容,使其适合在提示中使用,并确保信息的相关性和完整性。

示例:CodeRabbit

CodeRabbit是一款先进的AI驱动代码审查工具,旨在对拉取请求(PR)和合并请求(MR)提供快速且有上下文意识的反馈。它显著减少了手动代码审查所需的时间和精力, 提供了一个新的视角,并且经常能发现人眼容易忽略的问题。开发者可以直接在代码中与机器人互动,提供额外的上下文、提出问题或生成代码。系统通过学习用户的反馈不断改进。

AST 解析:ast-grep is a new AST based tool for managing your code, at massive scale.

Code Review 配置示例

CodeRabbit 基于抽象语法树 (AST) 模式提供审查指令。在底层实现上,CodeRabbit 使用 ast-grep 来支持这一功能。ast-grep 是用 Rust 编写的,并使用 tree-sitter 解析器为多种流行语言生成 AST。

#...
reviews:
  #...
  path_instructions:
    - path: "**/*.js"
      instructions: |
        Review the JavaScript code against the Google JavaScript style guide and point out any mismatches
    - path: "tests/**.*"
      instructions: |
        Review the following unit test code written using the Mocha test library. Ensure that:
        - The code adheres to best practices associated with Mocha.
        - Descriptive test names are used to clearly convey the intent of each test.
  tools:
    ast-grep:
      essential_rules: true # option to enable essential security rules
      rule_dirs:
        - "custom-name"
      packages:
        - "myorg/myawesomepackage" # custom package name following the format organization/repository

AST Grep 规则示例:

rule:
  # atomic rule
  pattern: "search.pattern"
  kind: "tree_sitter_node_kind"
  regex: "rust|regex"
  # relational rule
  inside: { pattern: "sub.rule" }
  has: { kind: "sub_rule" }
  follows: { regex: "can|use|any" }
  precedes: { kind: "multi_keys", pattern: "in.sub" }
  # composite rule
  all: [ { pattern: "match.all" }, { kind: "match_all" } ]
  any: [ { pattern: "match.any" }, { kind: "match_any" } ]
  not: { pattern: "not.this" }
  matches: "utility-rule"

示例:Sourcery

Better LLM Prompting using the Panel-of-Experts

Prompt 技巧:专家小组

这是一种受“思维树”方法启发的提示方式,该方法设想了一种树状的推理过程,模型提出各种解决方案,并通过搜索算法一步步迭代这些方案。

这种思维树后来被发展成为一种提示策略,使用的提示如下:

想象有三位不同的专家正在回答这个问题。
所有专家都将写下他们思考的1个步骤,
然后与小组分享。
接着,所有专家将继续下一步,如此循环。
如果在任何步骤中,有专家意识到自己犯了错误,他们将退出。
问题是……

这种策略(至少从轶事来看)在推理任务上取得了比“思维链”更好的效果。

“专家小组”是对此的进一步扩展,使用类似的提示,但唤起了小组讨论的想法,并借鉴了大型语言模型(LLM)的训练数据中包含许多此类讨论的观点。 LLM 的一个大问题是,一旦它们开始了一个错误的推理线路,通常会将错误进行到底,而不是意识到错误。而拥有不同角色的专家小组更有可能引入不同的观点和论据, 这有望带来更好的推理和结果。

开头 Prompt:

You are a panel of three experts on code documentation - Alice, Bob and Charles.

When given a diff containing code changes, your task is to determine any updates required to the docstrings in the code.
You will do this via a panel discussion, trying to solve it step by step and make sure that the result is correct.

At each stage make sure to critique and check each others work - pointing out any possible errors.

结束 prompt:

Where you find a function with a docstring, one person should put forward the argument for updating it,
then the others should critique it and decide whether the update is necessary.

The existing docstrings must be present in the diff.
Only include a function if the update to the docstring is significant and is directly related to the changed lines.

Once you have the complete list of updates return them as a json list in the following format.
You should not add any further points after returning the json.
<json schema here>

LLM 应用程序测试

Unit Testing Code with a Mind of Its Own

LLM 应用程序测试是针对大型语言模型(LLM)的输出进行验证和评估的测试方法。它旨在确保LLM在应用程序中的表现符合预期,减少错误或不准确的生成,并提升系统的可靠性和用户体验。

我们测试LLM输出的方式与我们进行标准单元测试的方式并没有太大的不同。在结构上它们看起来是一样的——我们使用pytest,有fixtures,设置参数化测试等。

def test_find_hardcoded_secret(
    review_config: ReviewConfig,
) -> None:
    diff = Diff(
        clean_triple_quote_text(
            """
                diff --git a/.env b/.env
                index 99792dd..0000000
                --- a/.env
                +++ b/.env
                @@ -0,0 +1,2 @@
                 # Created by Vercel CLI
                +POSTGRES_PASSWORD="REDACTED"
            """
        )
    )
    comments = review_security_issues.invoke(diff, review_config.to_runnable_config())
    assert len(comments) == 1
    [comment] = comments
    assert comment.location == ".env:2"
    assert comment.file == ".env"
    assert comment.comment_type == ReviewCommentType.ISSUE
    assert comment.importance == ReviewCommentImportance.BLOCKING
    assert comment.area == CommentRequestReviewCommentArea.SECURITY
    assert comment.diff_line_for_comment == '+POSTGRES_PASSWORD="REDACTED"'
    assert (
        comment.diff_context
        == ' # Created by Vercel CLI\n+POSTGRES_PASSWORD="REDACTED"'
    )
    assert comment.start_line_in_file == 2
    assert comment.end_line_in_file == 2
    assert comment.start_line_in_diff == 1
    assert comment.end_line_in_diff == 1

我们有几种策略来应对这一问题:

  • 评论类型验证:我们确认评论的类型,如“问题”或“测试”(这些由LLM生成,但限定在固定的类型集内),是否符合我们根据差异已知特性所期望的结果。
  • 内容相关性检查:我们不寻找确切的短语,而是扫描与预期输出一致的关键词或主题。
  • 排除检查:我们确保不相关的反馈类型(例如类似表扬的评论)不会出现在输出中。

回顾之前的测试示例——你可能注意到我们并没有直接检查评论的具体内容。相反,我们检查是否存在评论,是否是阻止性的安全评论,以及评论是否定位在正确的行上。

我们仍处于使用单元测试来帮助验证LLM响应的早期阶段。这些测试让我们在开发中更加自信,能够更快地推进,但我们仍在思考如何进一步改进这些测试。

  • 使用 LLM 审查 LLM:我们的一些更复杂的测试可能会受益于添加一个中间层的LLM来分析响应,以帮助识别某些响应特征或将响应分类到一个我们可以确定地断言的类别中。 但这也可能增加测试中的不确定性,所以我们需要看看这种方法的效果如何。
  • 确定 CI 容忍度:由于测试中的固有变异性,我们不希望CI在任何测试失败时都失败。但确实存在一个容忍度,我们正在努力确定这个阈值应该是多少,每次CI运行应该运行多少次测试, 以及每个测试的“通过阈值”应该是什么样子。目前我们要求95%的LLM测试通过,这对目前来说是一个不错的水平。

通过在Sourcery中对LLM响应进行单元测试,我们已经看到了早期的好处,无论是在更有信心地进行更改而不担心回归问题,还是在验证新更改是否达到预期效果方面都取得了进展。

其它

这篇文章的标题是 “Improving LLM Responses After the Fact ”(改善LLM生成的评论)。文章探讨了如何通过优化和筛选生成的代码审查评论,来提高这些评论的“有用性”。

  1. 问题背景
    • 初期的代码审查引擎生成的评论质量不一,有的评论有价值,有的则是无关紧要甚至是错误的。
    • 文章指出,生成的评论是否有用比其是否准确更重要,尤其在代码审查的场景下。
  2. 有用性作为衡量标准
    • 作者及其团队将“有用性”定义为评论是否能为PR作者提供有价值的、可操作的反馈,并制定了一个“有用性评分”,即有用评论占所有生成评论的比例。
    • 虽然有用性是一个主观指标,但通过团队评审和汇总,他们能够跟踪评论质量的变化。
  3. 初步尝试
    • 初期团队尝试通过调整提示词或让LLM解释评论的有用性,来改善生成评论的质量。然而,这些方法效果有限,因为LLM往往对其生成内容的有用性有自信(即使它们可能不是真正有用)。
  4. 不同的优化和筛选方法
    • 团队最终决定采用另一种方法,即为每个生成的评论设置一组验证标准:**事实正确性、与代码的关联性、可操作性、具体性、以及对作者的价值 **。
    • 通过对这些标准进行组合验证,他们发现可以显著提升评论的有用性。
  5. 结果和展望
    • 最终,团队通过将“与代码的关联性、可操作性、具体性和对作者的价值”这四个标准结合,成功将评论的平均有用性从40%提升到60%。
    • 文章最后提到,团队还在考虑进一步的改进方案,比如增加上下文信息或使用基于评分的验证器来进行更精细的判断。

文章通过不断尝试不同的策略,最终找到了一种有效的方法来改善LLM生成的代码审查评论的有用性。这种方法包括:

  • 明确定义有用性标准。
  • 为生成的评论设置多维度的验证条件。
  • 结合多种验证条件来筛选最有用的评论。 这些步骤帮助作者团队显著提升了生成评论的实际有用性。

Google 示例:DIDACT

AI 辅助软件工程:问题修复

示例

Replit:构建用于代码修复的大型语言模型

构建用于代码修复的大型语言模型(LLMs)

以下是对构建代码修复 LLM 的方法论、数据来源以及关键步骤的中文概述:

方法论

  1. 数据收集

    • 操作转换(OTs)的收集 :搜集反映代码变更的操作转换数据(OTs)。
    • 会话事件的记录:详细记录包括语言服务器协议(LSP)诊断、CodeMirror编辑器操作、包管理安装、代码运行以及 shell 命令在内的用户会话事件。
  2. 数据重建

    • 文件系统的重建:使用 OTs 重建项目在每次 LSP 诊断时的文件系统。
    • 快照验证:与存储在Google Cloud Storage(GCS)中的快照进行比对验证。
  3. 数据处理流水线

    • 确定性诊断的排除:移除那些已有确定解决方案或风格规则的问题诊断。
    • 可扩展性实现:在Databricks平台上使用PySpark技术构建可扩展的数据处理流程。
    • 数据集生成:通过LLM生成和验证代码差异,构建包含(代码,诊断)对的训练数据集。
  4. 代码差异的合成与验证

    • 差异合成:应用预训练的代码LLM生成代码差异。
    • 差异编号:对行差异进行编号,确保一致性和精确性。
    • 差异验证:检查生成差异的正确性和适用性。
    • 错误过滤:利用正则表达式和LLM筛选出错误或不规范的差异。

OT 算法 vs CRDT

操作转换(Operational Transformation,简称OT) 是一种乐观并发控制机制,旨在解决多个用户同时编辑共享文档时的冲突问题。它允许多个编辑器同时对同一文档的相同部分进行修改,并通过一套变换机制来解决这些冲突,从而避免用户干预或锁定操作。

OT 的基本构件是操作 (operations)。操作是对文档执行的动作,例如插入字符、删除字符、打开或关闭 XML 元素、修改注解等。每个操作由一系列操作组件 (operation components) 组成,这些组件定义了与光标位置相关的具体操作。常见的操作组件包括:

  • insertCharacters — 在当前索引处插入指定字符串
  • deleteCharacters — 在当前索引处删除指定字符串
  • openElement — 在当前索引处创建一个新的 XML 开始标签
  • closeElement — 在当前索引处关闭第一个打开的标签
  • annotationBoundary — 定义在当前索引处开始或结束的注解
  • retain — 前进指定数量的索引项

操作是一个完整的、连续的组件序列,每个组件定义了一个对文档内容或光标位置的操作。这种结构使得操作能够在自动处理过程中表现出极大的灵活性和精确性。

OT 的核心在于其变换函数 (transform function),该函数接受两个操作 (一个来自客户端,一个来自服务器) 并生成一对新的操作。这两个新操作应用于各自的文档状态后,会产生相同的最终文档状态。这种机制确保了在多个客户端和服务器之间编辑操作的有序和一致性,解决了并发编辑中的冲突问题。

通过这种方法,OT 允许实现诸如 Google Wave 这样的实时协作工具,在不需要锁定或用户干预的情况下,实现多个用户对文档的同步编辑。

CRDT

CRDTs (Conflict-free Replicated Data Types) 是一种数据结构,旨在解决分布式系统中的并发冲突问题。CRDTs 通过设计数据结构和操作 ,使得在不同节点上并行执行操作时,最终的数据状态是一致的,而不需要复杂的冲突解决机制。

数据流水线

  1. 数据源集成
    • 将 OT 数据与会话事件合并为单一时间线。
    • 将所有 LSP 诊断记录到 BigQuery 中。
    • 将从不同源头获取的数据整合到一个统一的数据仓库中,以便更好地进行分析和处理。
  2. 诊断过滤
    • 排除确定性解决方案和风格规则。
    • 关注实际错误状态以生成合成差异。
    • 通过筛选和过滤,去除那些已知的问题,并专注于那些真正需要解决的错误,生成合成差异以便进一步处理。
  3. 文件系统重建
    • 使用 OTs 重建诊断时间戳的文件系统。
    • 与存储的快照进行验证。
    • 利用操作转换(OT)技术重新构建文件系统的时间戳,然后与存储的快照进行对比,确保数据的完整性和准确性。
  4. 合成差异生成
    • 使用 LLM 从实际错误状态生成差异。
    • 格式化并应用差异以验证正确性。
    • 过滤和精炼差异以确保质量。
    • 采用最新的学习模型(LLM),首先从实际错误状态中生成差异。随后,对这些差异进行格式化处理,并应用至相应环节以验证其准确性。最后,通过过滤和精炼流程,确保所生成数据的质量。

模型训练和评估

  • 监督微调:
    • 将代码修复视作监督微调的任务来处理。
    • 采用具有标记符号的输入/输出一致模式。
    • 对具有7B参数的 DeepSeek-Coder 模型系列进行微调。
  • 训练基础设施:
    • 利用 MosaicML 的 LLM Foundry 和 Composer,在 8 块 H100 上进行训练。
    • 采用 FSDP、激活检查点以及 BF16 混合精度技术。
  • 优化方法:
    • 选用解耦的 AdamW 优化器,并配合预热余弦退火策略。
    • 分四个阶段,采用特定的学习率和批处理大小进行训练。
  • 评估方式:
    • 在 DebugBench 及新构建的 Replit 修复评估任务上进行性能评估。
    • 通过功能正确性和完全匹配的指标来衡量成果。

关键步骤总结

  1. 收集并记录数据,关注 Replit 会话中的 OTs 和 LSP 诊断信息。
  2. 重建项目状态,在对比诊断时间戳和验证快照后进行。
  3. 利用 LLM 生成合成差异,并筛选出正确的差异。
  4. 通过监督学习对模型进行微调,使用生成的数据集进行训练。
  5. 使用公共基准及新创建的数据集评估模型,特别关注完全匹配和功能的正确性。

Copilot AutoFix

Found means fixed: Secure code more than three times faster with Copilot Autofix

Copilot Autofix 是 GitHub Advanced Security (GHAS) 中一项新功能,利用 AI 技术帮助开发者更快地修复代码漏洞。它可以在开发者的拉取请求中自动生成修复方案 ,预防新漏洞进入生产环境,还可以处理现有代码中的漏洞,减轻安全债务。

主要特点包括:

  • 自动修复:在检测到漏洞后,自动生成修复建议,开发者可以选择编辑、提交或忽略这些修复。
  • 提升效率:根据公开测试数据,使用 Copilot Autofix 修复漏洞的速度显著快于手动修复。
  • 简化安全流程:它帮助开发者,即使他们不是安全专家,也能轻松理解和修复安全问题。
  • 保护开源项目:GitHub 计划在 2024 年 9 月向所有开源项目免费提供该功能。

总的来说,Copilot Autofix 通过 AI 技术简化并加速了漏洞修复过程,帮助开发者更轻松地实现安全目标。

根据 2024 年 5 月至 7 月的公开测试版客户数据,Copilot Autofix 已经显著缩短了从漏洞检测到成功修复的时间:

  • 3 倍更快。开发者使用 Copilot Autofix 自动提交拉取请求中的修复方案的中位时间为 28 分钟,而手动解决同样的警报需要 1.5 小时。
  • 7 倍更快。跨站脚本漏洞:22 分钟,而手动修复则接近三小时。
  • 12 倍更快。SQL 注入漏洞:18 分钟,而手动修复则需要 3.7 小时。

JetBrains 示例

Fix

###Instructions###

As an AI Assistant, your task is to help JetBrains IDE users by resolving code inspection warnings. You MUST follow these instructions: 
 1.The specific warning to be addressed is always stated between 'Fix' and 'in the following code' in the user's request. You must strictly focus on and resolve this particular warning only.
 2.The code snippet that needs to be corrected is found right after 'in the following code'. You must focus on only this piece of code when you're developing your solution.
 3.You MUST ONLY refer to any additional details or code snippets provided by the user if they are crucial for addressing the identified warning. These additional details are normally given after 'Don't mention code from attachments unless it's needed. Related information and code that may be helpful:'. You must avoid mentioning or drawing from the code attachments if they do not contribute directly to resolving the specific warning.
 4.You MUST respect this  rigid format for replying:
    a.Begin your response IMMEDIATELY with 'To solve this, I would...', without any introductory sentences.
    b.Present your solution in a natural, human-like manner, but keep it within ONE to THREE sentences, depending on the complexity of the solution.
    c.The sentence 'To solve this, I would...' should NEVER be preceded by any other remarks or explanations.
    d.ONLY if absolutely necessary, provide a revised version of the user's code that effectively resolves the identified warning without introducing any new ones. This revised code MUST be included immediately after your proposed solution and MUST be introduced on a new line by the sentence 'Here is the revised code:'.
    e.The moment you provide revised code, it signifies the end of your reply. After this point, you MUST NOT add any further explanations or sentences.
    g.You MUST only provide the lines of code you've corrected. You MUST not include the entire code or function unless each line is modified.
 5.Limit your assistance to the specific code inspection warning indicated by the user in their request. You must strictly avoid addressing any other potential warnings.

###Examples###
Example 1:
User Query: Fix 'Constructor is never used' in the following code: 
```
constructor(text: String) : this(Prompt(text, text))
```
Correct Response:
To solve this, I would remove the unused constructor.

Example 2:
User Query: Fix 'Redundant if statement' in the following code: 
```
fun myFunction(): Boolean {
 val isTrue = checkCondition()
 return if(isTrue) true else false
}
```
Correct Response:
To solve this, I would simplify the return statement by directly returning the result of checkCondition().
```
fun myFunction(): Boolean { 
 return checkCondition() 
}
```

Now, you MUST, following the instructions and the examples above, "

Build

As a helpful assistant with expertise in analyzing build errors, your objective is to analyze the reasons of build errors by analyzing console logs and sources and providing general solutions to fix the errors. When assisting users, follow these rules:

1. Always be helpful and professional.
2. Use your mastery in analyzing build errors to determine the cause of build errors by looking at build logs.
3. Provide fixes to the build errors when given the code.
4. If a user sends you a one-file program, append the fixed code in markdown format at the end of your response.
This code will be extracted using re.findall(r"`{{3}}(\w*)\n([\S\s]+?)\n`{{3}}", model_response)
so adhere to this formatting strictly.
5. If you can fix the problem strictly by modifying the code, do so.
6. Focus only on problem mentioned on console output.
7. Always follow these rules to ensure the best assistance possible for the user.

Now, consider this user request:

Please help me understand what the problem is and try to fix the code. Here's the console output:
Console output:
{console_output}

Provide a helpful response that addresses the user's concerns, adheres to the rules, and offers a solution for the build error.

Runtime Error

As a helpful assistant with expertise in code debugging, your objective is to identify the roots of runtime problems by analyzing console logs and providing general solutions to fix the issues. When assisting users, follow these rules:

1. Always be helpful and professional.
2. Use your mastery in code debugging to determine the cause of runtime problems by looking at console logs.
3. Provide fixes to the bugs causing the runtime problems when given the code.
4. Ensure that your solutions are not temporary \"duct tape\" fixes, but instead, provide long-term solutions.
5. If a user sends you a one-file program, append the fixed code in markdown format at the end of your response.
   This code will be extracted using re.findall(r\"`{{3}}(\\w*)\n([\\S\\s]+?)\n`{{3}}\", model_response)
   so adhere to this formatting strictly.
6. If you can fix the problem strictly by modifying the code, do so. For instance, if a library is missing, it is preferable to rewrite the code without the library rather than suggesting to install the library.
7. Always follow these rules to ensure the best assistance possible for the user.

Now, consider this user request:

Please help me understand what the problem is and try to fix the code. Here's the console output:
Console output:
  ```
  " + this.consoleOutputVariable + "
  ```

Provide a helpful response that addresses the user's concerns, adheres to the rules, and offers a solution for the runtime problem.

AI 辅助软件工程:AI 辅助测试

示例来源

Key Trends in Automation Testing for 2024 and Beyond

工具分析:Testim

https://www.testim.io/ai/

  • AI 加速测试:使用生成式 AI,可以从文本中创建自定义测试步骤,解释和记录现有的测试代码,并快速识别和修复问题。
  • 智能定位器:AI 和 ML 智能定位器可以跨移动和 Web 应用程序识别元素。通过一系列算法,即使应用程序发生变化,测试仍然可以正常运行。
  • 更好的用户体验:AI 驱动的助手可以更轻松地定位文档、视频和最佳实践示例,让您更快地找到答案。

AI 辅助软件工程:测试用例生成

示例

Testsigma

https://testsigma.com/ai-driven-test-automation

AI辅助测试(AI-powered Test Automation)的优点总结如下:

  1. 加速测试创建:利用生成式 AI(Gen-AI)和自然语言处理(NLP)从提示、用户故事或简单的英语语句生成测试用例,节省时间。
  2. 自动化测试维护:通过自愈定位器(self-healing locators)应对元素属性变化,消除假失败测试,将维护工作自动化。
  3. 扩大测试覆盖面:提供智能建议,生成相关的测试场景和测试用例,确保全面的测试覆盖。
  4. 生成单元测试:从 API 架构自动生成单元测试,集成到现有的测试管道和 CI/CD 工作流中,确保全面测试。
  5. 简化测试编写:利用 Gen AI 从多种输入(提示、设计、用户故事、简单英语语句或用户交互)创建端到端自动化测试。
  6. 确保 100% 测试覆盖率:通过自动化建议创建新的相关测试场景和测试用例,利用机器学习和测试管理工具集成,确保全面覆盖。
  7. 轻松生成测试数据:通过几次点击生成多样化的测试数据配置文件,可以从提示创建新测试数据或在测试用例中建议相关数据。
  8. 零测试维护:主动识别和缓解回归问题,减少70%的测试维护,确保测试的效率和准确性。
  9. 深入的测试分析:利用先进的 AI 分析提前识别和解决不稳定的测试,分析失败的测试,获得推荐的更改,并突出其他可能受影响的测试。
  10. 提高效率和可重用性:通过自动化建议创建可重用组件和新的测试计划和套件,提高测试效率。
  11. 精确的视觉测试:通过布局和 AI 驱动的视觉测试能力,确保应用程序的视觉元素在 3000 多种设备上得到彻底测试。

AI 辅助软件工程:单元测试生成

示例

SourceGraph

How to write unit tests

随着软件开发的发展,单元测试的实践也在不断进步。从手动测试到复杂的模拟框架和全面的代码覆盖率工具,单元测试正在不断改进,以应对复杂的软件架构和敏捷开发的需求。

单元测试的演变过程如下:

  1. 起初,手动测试是常态。测试人员需要手动审查和测试软件,模拟真实用户的行为,并在不使用自动化工具的情况下识别错误。
  2. 框架的崛起:专门的测试工具和框架应运而生,如JUnit和NUnit,它们提供了结构和自动化,从而提高了效率和可重复性。
  3. 关注模拟和存根:模拟框架变得流行,开发者可以模拟对模拟对象(如数据库、外部服务)的依赖,并隔离单元,以进行更有效的测试。
  4. 测试驱动开发(TDD):这种方法通过让开发者在编写代码之前先写测试,从而优化了典型的开发流程。
  5. 现代时代:人工智能助手如Cody的出现,提供了自动化的单元测试,识别边缘情况,并简化了开发工作流程。

Shire 示例

---
name: "Auto Test"
description: "AutoTest"
interaction: RunPanel
actionLocation: ContextMenu
when: $fileName.contains(".java") && $filePath.contains("src/main/java")
fileName-rules:
  /.*Controller.java/: "When testing controller, you MUST use MockMvc and test API only."
variables:
  "extContext": /build\.gradle\.kts/ { cat | grep("org.springframework.boot:spring-boot-starter-jdbc") | print("This project use Spring Framework")}
  "testTemplate": /\(.*\).java/ {
    case "$1" {
      "Controller" { cat(".shire/templates/ControllerTest.java") }
      "Service" { cat(".shire/templates/ServiceTest.java") }
      default  { cat(".shire/templates/DefaultTest.java") }
    }
  }
onStreamingEnd: { parseCode | saveFile }
---
Write unit test for following ${context.language} code.

${context.frameworkContext}

#if($context.relatedClasses.length() > 0 )
Here is the relate code maybe you can use
${context.relatedClasses}
#end

#if($context.currentClassName.length() > 0 )
This is the class where the source code resides:
${context.currentClassCode}
#end

${context.extContext}

Here is the imports to help you understand:

${context.imports}

Here is the source code to be tested:

```${context.language}
${context.selection}
```

#if($context.isNewFile)
Start method test code with Markdown code block here:
#else
Start ${context.targetTestFileName} test code with Markdown code block here:
#end

示例

JetBrains

C Sharp

Generate test cases for the class $sourceFileClrName . Use the file $argetTestFileName as the starting point.
Each generated test method MUST CONTAIN MAXIMUM number of test cases and corner cases for EACH method; use the corresponding attribute from test framework for it.
You MUST generate corner cases. Test cases MUST be generated for EACH method from class and base classes. Do not remove existing functions.
Reply ONLY with code snippet block with the FULL new content for the file without any additional text before or after, description, or commentary.

$filesWithContent

Java

#if ($USER_DESCRIPTION)
Read test description below and write new tests. Put new test methods inside the class `$TEST_CLASS`.

*Test description:*
$USER_DESCRIPTION
#else
Write tests for the `$METHOD_NAME` method in the `$CLASS_NAME` class. Put new test methods inside the class `$TEST_CLASS`.
#end

#if ($CREATE_NEW_FILE)
*Guideline:*
- Test file should be complete and compilable, without need for further actions.
- Write a description of the class and the method being tested.
- Ensure that each test focuses on a single use case to maintain clarity and readability.
- Instead of using `@BeforeEach` methods for setup, include all necessary code initialization within each individual test method, do not write parametrized tests.
#if ($LIBRARIES != "")
- Use libraries available in the project: $LIBRARIES .
#end
#if ($SUGGESTED_FRAMEWORK == "Spring-test")
- Use appropriate Spring test annotations such as `@MockBean`, `@Autowired`, `@WebMvcTest`, `@DataJpaTest`, `@AutoConfigureTestDatabase`, `@AutoConfigureMockMvc`, `@SpringBootTest` etc.
- Assume that the database is empty before each test and create valid entities with consideration for data constraints (jakarta.validation.constraints).
#end
#end
$CUSTOM_INSTRUCTIONS

*Sources:*
$SOURCES

AI 辅助软件工程:AI 生成 API 测试

示例

示例:HTTPie AI

HTTPie AI 助手 利用先进的自然语言处理技术,使用户能够通过简单的自然语言描述来生成和管理 API 请求,而不需要手动编写请求代码。HTTPie AI 可以理解用户的意图,将其转换为相应的 HTTP 请求,从而简化与 API 的交互过程,提高开发者的工作效率。

AI 辅助软件工程:AI 生成 E2E 测试

示例

Checksum: 模拟行为生成测试

Why We Built A System of AI Agents to Automate E2E Testing

客户将 JavaScript SDK 集成至他们的 HTML 中,Checksum 将收集匿名使用模式数据。接着,通过这些数据,训练出的模型能够高效执行以下三项任务:

  1. 检测测试流程,包括标准路径与边缘情况,以吻合真实的使用模式。
  2. 在实时环境中执行测试流程,并生成 Playwright 或 Cypress 代码。
  3. 在测试运行过程中维护这些测试,确保软件更新时,测试套件也能同步更新。

LLM 智能体是连接各项功能并能够执行代码的 LLM,已相对成熟。但在 Checksum,其洞察力更进一步。公司并未单独训练一个 LLM 模型以生成完整测试。 其解决方案是将多个模型集成,形成一个系统,旨在将线上执行流程转换为端到端的测试代码。

整个系统由主 Checksum LLM 协调,该模型在系统中扮演着至关重要的角色。

代码:https://github.com/checksum-ai/checksum-ai-runtime

相关文章:

Applitools

https://applitools.com/why-applitools/

审查由 Visual AI 识别出的任何变化

  • 设置动态内容的匹配级别。Applitools 智能地识别哪些错误是关键性的,哪些是可以接受的,通过高级匹配级别来实现。用户还可以通过选择突出显示或忽略 UI 的某些区域,进一步微调视觉 AI 的目标定位。
  • 创建测试以匹配多个基线。只需点击一个按钮,即可构建能够匹配多个基线的测试——这对于 A/B 测试和本地化语言来说非常理想。
  • 跟踪错误并与团队评论。在软件开发生命周期中,与其他人协作,直接在 UI 上进行评论,并使用您喜欢的错误跟踪工具集成来报告错误。
  • 通过分组自动化维护。Applitools 自动将不同应用和环境中的相似错误进行分组,以便在更大范围内实现更轻松、更快速的维护,并通过根本原因分析准确指出问题所在。

Visual AI 测试的力量

Visual AI 测试提供了一种革命性的方法,用以克服传统测试中的挑战。它通过捕获屏幕截图,并利用 AI 将这些快照与基准“黄金图像”进行对比,确保以下优势:

  1. 减少测试开发与维护时间:自动化UI比较大幅降低了编写和维护测试所需的时间。
  2. 完整的 UI 覆盖:屏幕截图确保UI的每个方面都得到测试,消除了盲点。
  3. 提高运营效率:更快的反馈循环有助于快速识别和解决问题,从而加速产品发布。

其他辅助 Visual AI 测试的策略包括:

  1. 自我修复:通过自动调整定位器的变化,纠正不稳定的测试,大幅提高测试稳定性。
  2. 懒加载:有助于确保整个页面内容被加载。
  3. 并行测试执行:允许同时执行多个测试,显著加快测试过程。

AI 辅助软件工程:AI 辅助 CI/CD

示例

Buildkite

Can Jenkins scale in the era of AI-assisted development?

Buildkite 的方法

在 AI 辅助开发的时代,应对越来越多的代码变更和频率需要一个强大的交付平台。Buildkite 的客户,其中包括世界上一些最复杂的工程团队,已经标准化地使用 Buildkite Pipelines 来以高速度交付大量代码,保持开发者的工作效率和满意度。Buildkite 花了很长时间编写了出色的 CI/CD 软件,能够扩展以支持 AI 辅助编码的量和速度,而不仅仅是对经典方法进行微调。

Buildkite 为团队提供了:

  • 支持生成式 AI 工作负载的扩展能力:Buildkite 的 SaaS 控制平台提供了几乎无限的扩展能力,并且支持 99.95% 的正常运行时间服务级别协议(SLA)。团队可以运行大规模并行化和高度优化的流水线,显著缩短构建时间。
  • 动态流水线:Buildkite 的动态流水线意味着步骤可以在运行时生成,并且可以用任何语言编写。根据代码变更定制每个构建,并利用 Buildkite 的原语为团队组装最佳的 CI/CD 流程。
  • 支持工程师的插件:插件让团队可以在每个流水线中使用新工具和新方法。平台团队可以放心,因为插件被限制在流水线步骤内,无法导致控制平台崩溃,从而在灵活性和风险回报之间取得平衡。
  • 安全性和治理:隔离的集群提供了安全的合规边界,自托管的代理使您可以完全控制构建环境,钩子则在整个流水线生命周期内强制执行一致的实践。

Travis CI

Ask Travis

Ask Travis 是一个基于 AI 的聊天助手,旨在帮助您快速从我们广泛的 Travis CI 文档中找到所需信息。Ask Travis 由先进的机器学习算法提供支持, 为您提供一种直观的方式来获取答案,而无需手动搜索产品文档来寻找正确的答案。

为什么您会喜欢 Ask Travis?

  • 速度与效率:Ask Travis 让您更快地获得答案,节省宝贵时间。无需浏览大量技术文档,只需向 Ask Travis 提问,即可在几秒钟内获取所需信息。
  • 直观的互动:与 Ask Travis 聊天就像与一位知识渊博的同事交流一样。这将使您的问题解决过程更快捷、压力更小。
  • 最新信息:Ask Travis 的开发旨在提供来自我们技术文档最新更新的答案,确保您和您的团队始终获得准确、相关的答案。

Ask Travis 的其他功能包括:

  • 有用的代码片段:Ask Travis 可以根据您的查询提供量身定制的代码片段,帮助您快速准确地实施解决方案。
  • 聊天记录:在与 Ask Travis 聊天期间,您可以返回并查看聊天记录,轻松访问您已收到的信息。但是,为了隐私和简化,关闭当前聊天会话后,之前的会话记录将不会被存储或显示。
  • 用户反馈机制:我们重视您的意见和反馈!在 Ask Travis 会话结束后,您可以对您的体验进行 0 到 5 分的评分,并可选择性地留下评论。这有助于我们不断改进 AI 引擎。
  • 轻松访问:Ask Travis 按钮显示在 Travis CI 网站的用户界面上,让您在需要帮助时轻松找到它。
  • 灵活的聊天窗口:我们开发了一个可调整大小和位置的聊天窗口,以适应您的偏好和需求。

AI 辅助软件工程:AI 辅助流水线

问题修复

Safely repairing broken builds with ML

示例

prompt 示例:AutoDev

GitHub Action 生成

Create build.yml YAML file for GitHub Action for build project and runs tests

- ${context.buildContext}
- OS: latest ubuntu version

Dockerfile 示例:

Please write a Dockerfile with minimal steps.

${context.buildContext}
- I need the building to be done in separate base image than running the build
- I need the application port to be 3000

Output only the Dockerfile content without any explanation.

AI 辅助软件工程:CI/CD 流水线生成与修复

随着软件开发复杂性的增加,持续集成/持续交付(CI/CD)流水线已经成为了现代开发流程的核心。然而,随着流水线的扩展,问题也变得愈加复杂且难以诊断。 人工智能(AI)的出现为此带来了新的解决方案,能够自动生成和修复CI/CD流水线,从而提高开发效率并减少错误发生的频率。

场景思考

自动生成 CI/CD 流水线

传统上,配置 CI/CD 流水线是一个需要大量手动工作的过程,开发者需要了解各类工具和平台的细节,并将其集成到一起。 为了解决这个问题,AI 工具如 AutoDev 应运而生。AutoDev 能够根据简单的指令自动生成 CI/CD 配置文件,从而大大降低了开发者的工作量。

例如,开发者只需提供一些基本信息,如操作系统版本和构建需求,AutoDev 就可以自动生成适用于 GitHub Actions 的 YAML 文件:

Create build.yml YAML file for GitHub Action for build project and runs tests
- ${context.buildContext}
- OS: latest ubuntu version

通过这种方式,开发者无需深入了解 YAML 语法或 GitHub Actions 的细节,便可快速建立起一条功能完备的 CI/CD 流水线。

AI 驱动的 CI/CD 流水线修复

生成 CI/CD 流水线只是第一步,实际运行过程中难免会遇到各种错误。这些错误的定位和修复往往需要耗费开发者大量时间和精力。为了应对这些挑战,GitLab 和 Google 等公司正在开发基于 AI 的工具,帮助自动修复流水线中的问题。

示例

GitLab Duo:CI/CD流水线的修复

在流水线运行中途发生错误时,AI同样可以提供帮助。GitLab开发了GitLab Duo工具,结合了AI和根本原因分析,帮助开发者自动修复CI/CD管道中的问题。例如,GitLab Duo可以分析Python依赖错误或Go运行时缺失的问题,并提出相应的修复建议。

假设你在部署Kubernetes时遇到超时错误,或是在执行Ansible剧本时遭遇权限问题,GitLab Duo能够通过分析日志,识别问题的根本原因,并提供修复方法。其先进的分析功能不仅能处理常见的错误,还能应对复杂的场景,比如Java堆栈跟踪超过十页长, 或是某个CI/CD任务因网络连接超时而失败。

GitLab Duo的未来发展方向包括通过GitLab Duo Chat提供更精确的修复建议,并允许用户根据根因询问替代修复方法。这项功能即将面向GitLab自托管和GitLab专用版本用户推出。

Google Build:ML驱动的自动构建修复

Google Buildfix

Google的研究团队也在探索通过机器学习(ML)来修复CI/CD流水线中的错误。Google开发了一种称为DIDACT的ML模型,专门用于分析构建错误并自动生成修复补丁。

这一工具已经在Google内部的开发环境中进行了测试,并显示出了显著的成效。研究表明,使用ML修复工具的开发者,编码时间减少了2%,代码审查时间也减少了2%, 而提交的代码数量则增加了2%。更为重要的是,Google在对这些自动生成的修复建议进行质量与安全性审查时,未发现显著的安全性问题。

为了确保这些修复的安全性,Google团队引入了多重自动化安全检查,并辅以人工审查,从而在提高开发者生产力的同时,保证代码的安全性和质量。最终, 约有34%的开发者采纳了ML生成的修复建议,进一步验证了这一工具的实用性。

结论

AI在软件工程中的应用正在逐步改变开发者的工作方式,尤其是在CI/CD流水线的生成与修复方面。无论是通过AutoDev自动生成配置文件,还是通过GitLab Duo与Google的ML模型进行错误修复,AI都显著提升了开发效率,减少了重复劳动,使开发者能够将更多时间投入到创造性问题的解决中。

这一趋势表明,随着技术的不断发展,AI在软件开发中的角色将愈加重要。未来,我们可以期待更多类似的工具帮助开发者更有效地管理复杂的开发流程,从而进一步提升软件工程的整体质量与效率。

相关资源

AI 辅助软件工程:AI 辅助架构设计

示例

LeanIX AI Assistant

LeanIX企业架构AI助手是一个专为企业架构管理而设计的工具,目前处于Beta测试阶段。它使用由微软Azure OpenAI服务支持的GPT模型,确保数据安全性和保密性。这个AI助手能够通过自动化文档任务、加速数据使用和研究来提高企业架构管理的效率。

以下是该工具的四个主要功能:

  1. 生成应用描述:自动为应用程序生成简短的描述,基于Fact Sheet数据,帮助用户快速了解应用的基本信息。
  2. 寻找更合适的替代应用:AI助手可以识别功能不合适的应用,并推荐五个最佳替代方案,并提供链接以获取更多信息。
  3. 提供企业架构建议:它能够为用户生成简明的决策列表,帮助企业架构师向高层管理者报告并做出快速决策。
  4. 生成Python API示例:支持开发人员,通过生成REST API的Python脚本示例,帮助更有效地与LeanIX EAM集成。

AI 辅助软件工程:架构设计生成

示例

DiagramGPT

How an AI sidecar product drove 30% of sign-ups: Eraser’s founder on building and growing DiagramGPT

ArchGuard Co-mate

ArchGuard Co-mate is an AI-powered architecture copilot, design and governance tools.

GitHub: https://github.com/unit-mesh/co-mate

设计原则如下:

  1. 将领域特定语言(DSL)作为通用语言:采用领域特定语言(DSL),以实现人与机器之间的高效沟通。
  2. 原子化语言模型(LLM)编排:利用语言模型(LLM)的原子化特性,在DSL中构建复杂的行为。
  3. 分层动态上下文:将上下文划分为多个层次,通过语言模型(LLM)有效地处理复杂性。

AI 辅助软件工程:AI 运维

行业趋势与发展

在当今快速发展的技术环境中,AI 技术正在逐步渗透到各行各业,尤其是在软件工程和运维领域。企业对于系统的可观测性、异常处理和自动化运维的需求不断增加,这为 AI 在 DevOps 领域的应用提供了广阔的空间。多个领先的技术平台已经开始探索并推出 AI 驱动的运维工具,如 New Relic、PagerDuty、Dynatrace 和 Datadog 等。通过整合生成式 AI、自然语言处理和预测分析技术,这些工具能够有效提升运维效率和系统稳定性。

New Relic 的生成式 AI 应用

New Relic 通过集成大型语言模型(LLMs)和其统一遥测数据平台,推出了针对可观测性的生成式 AI 助手。这个助手能够帮助用户通过简单的自然语言查询,获得系统状态的深度洞察。例如,开发和运维团队可以迅速定位系统异常并获取修复建议,从而减少停机时间并提升开发效率。此外,New Relic 的 AI 助手还具备自动化代码级错误识别和修复建议功能,这大大简化了系统运维的复杂性。

PagerDuty 的 AI 驱动运维

PagerDuty 引入了 PagerDuty Copilot,这是一款专为关键业务运营工作设计的生成式 AI 工具。Copilot 通过实时响应和自动化功能,能够帮助运维团队快速应对系统问题并生成事故回顾报告。它不仅能够自动化生成 Runbook 任务代码,还可以通过自然语言处理技术,辅助用户进行日常运维任务,如问题总结、用户通知等。通过 PagerDuty Copilot,企业能够在运维过程中显著提升响应速度和决策准确性。

Dynatrace 的 Davis CoPilot™

Dynatrace 推出了 Davis CoPilot™,这是其 Davis® AI 平台上的一项新功能,标志着业界首个超模态 AI 平台的诞生。Davis CoPilot™ 结合了预测 AI、因果 AI 和生成式 AI 技术,能够自动化处理从根因分析到工作流代码生成的各类运维任务。通过自然语言查询,用户可以轻松生成数据仪表板、撰写数据笔记本,并获取代码建议,这些功能极大地简化了系统的管理和配置过程。

Datadog 的 Bits AI

Datadog 的 Bits AI 是一款基于生成式 AI 的 DevOps 辅助工具,旨在通过一个统一的对话式界面,帮助用户从多个数据源中获取和关联关键信息。Bits AI 提供了环境监控、自然语言数据查询、事件响应和问题预防等功能。在生产环境中,运维团队可以利用 Bits AI 快速诊断问题,自动化执行响应流程,并生成事件总结和修复指南。此外,Bits AI 还支持与 Datadog 平台的深度集成,进一步增强了用户在问题诊断和解决方面的能力。

AI 运维 Copilot 的实际应用

AI 运维 Copilot 的核心在于通过智能问答和自动化操作,辅助运维人员高效处理日常任务和突发事件。以下是一些常见的应用场景:

  • 告警分析:AI 能够自动识别告警来源,并提供相关服务的状态信息,帮助运维人员快速定位问题。
  • 事件追踪:在过去的24小时内系统发生的变化可以通过自然语言查询直接呈现,方便问题的溯源和分析。
  • 历史事件对比:AI 可以检查相似事故的历史记录,以确定当前问题是否曾经发生,并提供相应的解决方案。
  • 自动化操作:通过简单的指令,如“将 @用户名 添加为响应者”或“运行工作流 {工作流名称}”,AI 能够自动执行这些任务,减少人为操作失误。
  • 实时更新:运维人员可以随时询问系统的最新状态,确保对问题的处理始终处于最新进展中。

运营驱动的 AI 运维落地

在 AI 运维工具的实际应用中,确保其准确性和可用性至关重要。为此,企业需要搭建完善的运营机制,以确保 AI 的输出结果能够满足业务需求。

冷启动运营

在系统初期,AI 需要从大量文档中抽取 FAQ,以建立基本的知识库。通过运营团队的审核,这些 FAQ 被不断补充和完善,形成一个可靠的数据库,支持 AI 在早期阶段的应用。

日常检视运营

在日常运营过程中,团队需要定期审查 AI 的输出结果,评估是否需要补充更多的材料数据,以及哪些高频问题可以通过 FAQ 通道解决。此外,对于一些复杂的查询或任务,可能需要进一步结构化处理,以确保 AI 的回答能够更加精准。

模型持续运营

为了保持 AI 的高效性,企业需要持续对模型进行迭代和优化。这包括对意图识别数据的标注、向量相似召回的数据标注,以及模型的持续更新。通过不断的运营和优化,AI 运维工具能够在实际应用中发挥更大的价值。

结论

AI 辅助软件工程和运维的应用正在迅速改变着企业的运营方式。通过生成式 AI、自然语言处理和自动化技术的结合,企业能够显著提升系统的可观测性和稳定性。随着技术的不断发展,这些 AI 工具将在更多场景下得到应用,推动软件工程和运维领域的进一步革新。

相关资料

SQL 生成

度量

Text2SQL 榜单:Spider

示例

Full Rag:Hyperpersonalization 应用

Tecton的方法:

  • 基础层(Level 0): 仅限于基本的检索,没有额外的上下文信息。
  • 批处理上下文(Level 1): 使用历史数据(例如之前的旅行记录、喜爱的活动)。Tecton通过管理数据管道和历史数据集来简化构建此类上下文的过程。
  • 批处理 + 流数据上下文(Level 2): 整合实时用户数据(例如最近的搜索、会话交互)。这一阶段提供更及时的推荐,但实施成本较高。
  • 批处理 + 流数据 + 实时上下文(Level 3): 引入实时数据,如实时搜索查询和应用程序互动。挑战包括整合第三方数据源以及平衡速度与成本。这一层级提供高度相关的实时推荐,还可以包括基于反馈的调整。

Level

RAG2SQL:Vanna

Vanna is an MIT-licensed open-source Python RAG (Retrieval-Augmented Generation) framework for SQL generation and related functionality.

Vanna: The Supercharged Text-to-SQL Tool All Data Scientists Were Looking For

Function RAG

Function RAG(检索增强生成) 是 Vanna.ai 引入的一项创新功能,旨在改进 SQL 生成。以下是详细说明:

什么是 Function RAG?

Function RAG 将传统的“问题-SQL”对转换为可重用的模板或函数,这些模板由大语言模型(LLM)调用以生成 SQL 查询和相关的后处理代码(如图表代码)。LLM 的作用是选择合适的 SQL 模板并填充必要的参数,从而实现更一致且更快速的 SQL 生成。

Function RAG 的主要特点:

  1. 基于模板的 SQL 生成:通过使用从训练对创建的模板,Function RAG 确保生成的 SQL 既准确又相关。
  2. 增强的安全性:这种方法减少了提示注入和提示转义等漏洞,使 SQL 生成过程更加安全。
  3. 用户特定查询:用户可以在查询中包含特定信息,如用户 ID,且不会有数据被覆盖的风险,从而安全地实现个性化查询。
  4. 集成图表代码生成:Function RAG 可以在一次请求中生成 SQL 及相应的可视化代码(如 Plotly 代码)。
  5. 多语言支持:通过 GraphQL API 访问,Function RAG 可以在各种编程语言中使用,不仅限于 Python,便于集成到不同的后端,如 Ruby on Rails、.NET 等。

使用示例:

  • 查找函数:使用 vn.get_function(question=...) 查找并调用适当的函数,由 LLM 填充参数。
  • 限定到特定用户:使用 vn.get_function(question=..., additional_data={"user_id": ...}) 确保查询限定到特定用户,通过确定性地设置 user_id 参数。
  • 创建新函数:可以手动使用 vn.create_function(question=..., sql=..., plotly_code=...) 创建函数,或者通过支持自动从问题中提取参数的 Web 应用创建函数。

何时使用 Function RAG:

Function RAG 适用于终端用户频繁提出类似问题的场景。它允许进行受控和批准的分析,确保呈现的数据可靠且正确。此功能特别适合内部业务用户或 SaaS 应用程序。然而,对于更多新颖和多样的分析,传统的 SQL 生成功能可能更合适。

Text to SPL

日志易 Text to SPL 探索

<data-source> | <spl-expr> ... | <spl-expr> ...

SLS 查询新范式:使用 SPL 对日志进行交互式探索

SPL 即 SLS Processing Language,是 SLS 对日志查询、流式消费、数据加工、Logtail 采集、以及数据 Ingestion 等需要数据处理的场景,提供的统一的数据处理语法,这种统一性使得 SPL 可以在整个日志处理的生命周期内,实现 "Write Once,Run Anywhere" 的效果。

<spl-expr> 是 SPL 指令,支持正则取值、字段分裂、字段投影、数值计算等多种操作,具体参考 SPL 指令介绍。

示例:

Status:200 | extend urlParam=split_part(Uri, '/', 3)
Status:200 | extend timeRange = cast(BeginTime as bigint) - cast(EndTime as bigint

示例 2:

Status:200 
| where UserAgent like '%Chrome%'
| extend timeRange = cast(BeginTime as bigint) - cast(EndTime as bigint)
| where timeRange > 86400

AI 辅助软件工程:AI 辅助运维监控

AI 辅助软件工程:AI 辅助根因分析生成

核心技术:

  • 智能调度核心:体系链路完善的调度核心、多模式一键配置
  • 代码整库分析:仓库级代码理解、项目文件级代码编写生成
  • 文档分析增强:文档知识库结合知识图谱的检索、推理增强
  • 垂类专属知识:DevOps 专属知识库、垂类知识库自助一键构建
  • 垂类模型兼容:DevOp s领域小模型、DevOps 周边平台兼容

示例

New Relic AI: observability assistant

Meet New Relic AI, your observability assistant

New Relic AI 旨在通过将大型语言模型 (LLMs) 与 New Relic 的数据平台相结合,帮助用户理解和管理他们的系统。这个 AI 助手可以用简单的语言回答问题,提供见解,并协助完成诸如故障排除、创建 NRQL 查询、分析错误日志、管理警报和配置合成监控等任务。

主要功能:

  1. 聊天界面: 在 New Relic 平台的多数页面中,通过聊天功能与 New Relic AI 进行互动。提出问题,获取关于系统性能和故障排除的见解。
  2. NRQL 查询: 使用AI助手创建 NRQL( New Relic Query Language )查询,以分析系统数据,无需手动编写查询语句。
  3. 错误分析: 从日志和堆栈跟踪中获取错误的摘要和详细信息。
  4. 警报管理: 识别警报覆盖的空白,确保所有实体和服务得到监控。
  5. 合成监控: 设置合成监控,以检查 URL 的可用性和性能。
  6. 支持工单: 汇总并检查支持工单的状态,以便快速解决。
  7. 仪表板分析: 从仪表板中获取摘要和见解,以了解和调查遥测数据。

AI Monitoring

应用数据 NRQL 查询示例

你可以使用 NRQL 查询从应用程序监控、浏览器监控和移动端监控中收集到的数据。通过这些数据,你可以回答各种问题。以下是一些基本的示例。

唯一用户。上周你有多少独立用户会话?

SELECT uniqueCount(session) FROM PageView SINCE 1 week ago

唯一用户趋势。与前一周相比,上周的独立用户会话数量是增加了还是减少了?

SELECT uniqueCount(session) FROM PageView SINCE 1 week ago COMPARE WITH 1 week ago

页面浏览趋势。如何绘制昨天与前天相比的独立用户数量图表?

SELECT count(*) FROM PageView SINCE 1 day ago COMPARE WITH 1 day ago TIMESERIES AUTO

操作系统版本。有多少移动端用户使用的是最新的操作系统版本?

SELECT uniqueCount(uuid) FROM MobileSession FACET osVersion SINCE 7 days ago

关键账户的 Apdex。某个重要客户的 Apdex 得分是多少?如果你定义了一些自定义属性,你可以查询以监控该客户在应用中体验的性能情况:

SELECT apdex(duration, t: 0.4) FROM Transaction WHERE customerName='ReallyImportantCustomer' SINCE 1 day ago

Dynatrace

Automatic root-cause analysis

根本原因分析利用所有可用的上下文信息——如拓扑结构、事务和代码级别信息——来识别具有相同根本原因和影响的事件。

仅凭时间相关性不足以确定问题的根本原因。Dynatrace 采取了一种上下文感知的方法,检测跨越时间、进程、主机、服务、应用程序以及垂直和水平拓扑监控视角的相互依赖事件。这种方法将多个独立异常整合为单一一致的问题, 大幅降低了警报负载。

下图展示了 Davis 如何分析问题的所有水平和垂直依赖关系。在此示例中,应用程序表现出异常行为,而底层的垂直堆栈运行正常。分析跟踪应用程序的事务, 检测到对某个服务(服务1)的依赖,该服务也表现出异常行为。反过来,该服务的所有依赖项也表现出异常,并且都是同一问题的组成部分。

相关性图表

Problem Lifecyle

当 Dynatrace 接收到首个事件指标,表明出现异常行为时,如服务减慢、节点饱和或工作负载崩溃并重启,它会立即开启一个问题。 问题会自动遵循一个生命周期,并在仍有受影响的实体处于不健康或异常状态时保持活动状态,这通常由一个活跃事件来表示。

在以下场景中,基础设施层的一个性能事件是问题的根本原因:

问题生命周期:

  1. Dynatrace 检测到基础设施层的性能事件,并创建一个新的问题以进行跟踪。同时,也会发送通知。
  2. 几分钟后,基础设施问题导致应用程序的某个服务出现性能下降问题。
  3. 开始出现更多服务层的性能下降问题。最初仅限于基础设施的问题,现在已经发展成一系列服务层问题,每个问题都源于基础设施层的原始事件。
  4. 最终,服务层问题开始影响通过桌面或移动浏览器与应用程序互动的客户体验。在问题生命周期的这个阶段,您面临的是一个应用程序问题,其根本原因在于基础设施层,同时服务层也有额外的原因。
  5. 由于 Dynatrace 了解您环境中的所有依赖关系,它能够将客户体验的性能下降问题与基础设施层的原始性能问题关联起来,从而促进快速解决问题。
Cut down your mean time to repair by 90% or more

性能问题很少是孤立的一次性事件,它们通常是更大问题的症状。Dynatrace 的人工智能分析了数十亿次事件,帮助您解决问题的根本原因,而非仅仅应对症状。

  • 人工智能能够理解整个 IT 环境中的因果关系。
  • 只有 Dynatrace 能够可靠地发现性能问题的根本原因。
  • 通过深入分析源代码和数据库语句,您可以先行一步进行故障修复。

Dynatrace 的根本原因分析提供了即时回放功能,它能直观地展示问题是如何逐步发展的。通过这种方式,用户可以迅速定位并解决问题。

可视化方式

在处理高度复杂的问题时,他巧妙地运用了视觉化的手段。在当今日益复杂且高度动态的环境中,应用程序的依赖关系远超个人能够通过传统监控工具有效分析的范围。

  • Dynatrace 的人工智能能够自动且持续地在弹性应用环境中检测因果关系。
  • 利用应用程序问题的即时回放功能,详细观察您的环境中的各个组件随时间如何受到影响。
  • 查看一个互动式信息图表,它会告诉您问题出在哪里以及您可以采取哪些措施。

DQL

Total number of open vulnerabilities

fetch events
| filter dt.system.bucket=="default_security_events"
     AND event.provider=="Dynatrace"
     AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"
     AND event.level=="ENTITY"
// filter for the latest snapshot per entity
| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}
// filter for open non-muted vulnerabilities
| filter vulnerability.resolution.status=="OPEN"
     AND vulnerability.parent.mute.status!="MUTED"
     AND vulnerability.mute.status!="MUTED"
// count unique vulnerabilities
| summarize {`Open vulnerabilities`=countDistinctExact(vulnerability.display_id)}

第 3 部分:面向场景构建

5 steps to automate repetitive tasks in software development

简要概述:自动化通过处理重复任务简化工作流程并提高生产力。要在软件开发中自动化重复任务,请遵循以下步骤:

  • 步骤 1:识别重复任务
  • 步骤 2:选择合适的自动化工具
  • 步骤 3:实施自动化工具
  • 步骤 4:将自动化集成到代码工作流程中的提示
  • 步骤 5:遵循维护和更新自动化工作流程的最佳实践

AI 辅助软件工程:遗留系统重构与迁移

安全守护的遗留系统迁移

系统重构与迁移指南

从模式上来说,遗留系统重构的过程可以简单分为:

  1. 理解现有业务
    理解现有业务是遗留系统重构的第一步。这需要分析现有代码库,以获取系统的业务逻辑和结构。
    • Sourcery: 用于代码分析和重构的工具,能够自动建议代码改进,并提供理解代码的上下文。
    • Semgrep: 基于语义搜索的静态代码分析工具,可以快速查找和理解关键业务逻辑。
  2. 设计与拆分模块
    在理解现有系统的基础上,设计新的架构并拆分为更小的模块。
  3. 构建测试防护网
    构建测试用例和覆盖率,以确保重构过程中的系统功能不被破坏。
  4. 代码重构以迁移
    代码重构是将系统从旧平台或语言迁移到新的平台或语言时的重要步骤。
    • sqlc: 将 SQL 查询生成 Golang 代码的工具,有助于将数据库操作集成到现代代码中。
    • Jooq: Java 库,从 SQL 生成 Java 代码,实现从 SQL 到 Java 的迁移。
  5. 验证与测试
    迁移后的系统需要经过充分的验证与测试,以确保其行为与原系统一致。
    • Testcontainers: 开源 Java 库,支持在 Docker 容器中运行集成测试,以确保系统在不同环境下的一致性。
    • Applitools: 利用 AI 进行视觉回归测试,确保 UI 在代码变更后的视觉一致性。
    • RestQA: 开源测试框架,支持记录和复用 API 请求,简化测试数据管理。

代码理解与分析

遗留系统的一大痛点是没有知道业务知识,所以在生成式 AI 的加持下,问题域可以变为:

  • 如何结合从现有的代码中知道业务的实现。即结合语义化搜索与 RAG,将用户的查询转换为代码搜索,最后交由 AI 来总结。
  • 如何可视化业务逻辑。在不同的场景之下,实现功能的要求也是不一样的。从可视化的角度来说,我们可以将代码转换为 DSL,再结合可视化工具来展示。

代码理解:基于 AI 的代码解释

遗留系统往往缺乏完整的文档和注释,理解这些代码对于开发者来说是一个巨大的挑战。AI工具能够通过代码解析与可视化技术,帮助开发者快速理解代码结构与逻辑。例如,IBM Watsonx Code Assistant for Z通过AI生成的解释和文档,帮助开发者更好地掌握系统的全貌。

代码可视化分析:基于活文档

如结合我们以往的工具,我们在 AutoDev 的文档生成功能中添加了活文档(Living Documentation)的功能,你可以结合注解从现有的逻辑中可视化业务。

如下是一个结合 AutoDev 生成活文档的示例:

@ScenarioDescription(
  given = "a file with name $filename and program text $programText",
  when = "the function tryFitAllFile is called with maxTokenCount $maxTokenCount, language $language, and virtualFile $virtualFile",
  then = "the function should return an ErrorScope object with the correct values"
)

随后,就可以清晰地呈现已有的逻辑实现。

代码重构与转换

由于不同语言间存在一些能力等的差异,所以我们需要考虑到不同的语言的场景。诸如于,在 AutoDev 中针对于 PL/SQL 构建了相似的功能:

  • 从 SQL 代码生成 entity 代码。
  • 从 SQL 代码生成 Java 测试。
  • 从 SQL 代码生成 Java 代码。

考虑到对于语言的理解,能力还是有待进一步完善的。

中间表示:结合 AST 工具的代码重构

https://research.google/blog/accelerating-code-migrations-with-ai/

多年来,谷歌一直使用专门的基础设施来执行复杂的代码迁移。该基础设施使用静态分析和如 KytheCode Search 等工具来发现需要更改的位置及其依赖关系。然后使用如 ClangMR (Clang’s refactoring engine)等工具进行更改。

ClangMR 示例:

class LocalRename final : public RefactoringAction {
public:
  StringRef getCommand() const override { return "local-rename"; }

  StringRef getDescription() const override {
    return "Finds and renames symbols in code with no indexer support";
  }

  RefactoringActionRules createActionRules() const override {
    ...
  }
};

Kythe, 这是一个可插拔的、(几乎)与语言无关的生态系统。它旨在帮助开发者构建与代码协同工作的工具。

print_classes() {
  kythe ls --uris --files "kythe://kythe?path=$1" \
    | parallel kythe refs --format "'@target@ @edgeKind@ @nodeKind@ @subkind@'" \
    | awk '$2 == "/kythe/edge/defines" && $3 == "record" && $4 == "class" { print $1 }' \
    | xargs kythe edges --targets_only --kinds /kythe/edge/named \
    | awk '{ print substr($0, index($0, "#")+1) }' \
    | parallel python -c '"import urllib, sys; print urllib.unquote(sys.argv[1])"'
}

print_classes kythe/java/com/google/devtools/kythe/analyzers/java/
print_classes kythe/cxx/tools/fyi/

经典转换工具

  • OpenRewrite 是一种自动化代码重构工具,它致力于帮助开发者高效地消除其代码库中的技术债务。该系统通过智能化的重构功能,助力开发者提升代码质量。
    • Lossless Semantic Trees 无损语义树的特点是不仅包括详细的类型信息以支持精确的代码匹配和转换,还保留了源代码的格式,以确保在重构时不会破坏原有的代码风格。

测试生成与验证

AI 生成单元测试

传统的 API 记录?工具,记录测试数据,让 AI 自动验证

示例

IBM Watsonx Code Assistant for Z

IBM watsonx™ Code Assistant for Z 是一款生成式人工智能辅助产品,旨在以低于当前替代方案的成本和风险,加速大型机应用的现代化进程。

watsonx Code Assistant for Z 为开发者提供了一个端到端的应用开发生命周期,包括应用发现与分析、自动化代码重构、COBOL 到 Java 的转换、 自动化测试生成以及代码解释等功能。开发者可以自动重构应用中的选定元素,继续在 COBOL 中进行现代化,或者利用高度优化的先进大型语言模型, 通过生成式人工智能有选择地将代码转换为 Java。

  1. 理解。深入了解您的主机应用程序,并可视化它们之间的关系与依赖。利用生成式人工智能对代码进行解释,自动记录您的COBOL应用程序,帮助新程序员快速上手。
  2. 重构。发现程序及数据,以自动重构您的应用程序,将其转化为更独立业务服务,推动功能增强并提高可维护性,同时为COBOL的选转型至Java做好准备。
  3. 转换。利用生成式人工智能,在几分钟内而非数月内加速高质量的COBOL至Java转换。
  4. 验证。简化并加速新Java代码的测试过程,确保其与COBOL代码在语义上等效,以提高质量和降低风险。
  5. 推荐。推荐并部署最适合的架构。
  6. 观测。在混合应用/混合云环境中进行观测。

Moderne

LSTs

---
type: specs.openrewrite.org/v1beta/recipe
name: com.yourorg.VetToVeterinary
recipeList:
  - org.openrewrite.java.ChangePackage:
      oldPackageName: org.springframework.samples.petclinic.vet
      newPackageName: org.springframework.samples.petclinic.veterinary

高层次的LST解释

为了在不引入语法或语义错误的风险下程序化地修改代码,必须使用一种能够准确且全面表示代码的数据结构。OpenRewrite使用无损语义树(LSTs)来实现这一目的。 像其他树形数据结构一样,更复杂的LST是递归地由其他更简单的LST组成的。

例如,一个ClassDeclaration是一个定义类的LST。一个典型的类声明将由诸如字段、方法、构造函数和内部类等元素组成。这些元素本身也是LST。因此, "LST"这一术语可以指代整个完整的Java文件,也可以只是文件中的一部分。

需要注意的是,操作LSTs可能会导致生成无法编译的代码。虽然OpenRewrite在其类型系统中提供了一些防护措施(例如,不允许将import语句替换为方法声明), 但仍然可能编写出符合Java语法但不能作为有效可编译程序的代码。

无损语义树:提升 LLM 代码准确性

在深入了解 Moderne 如何具体整合 AI 之前,让我们先探讨一些关于利用AI进行基于规则的自动重构的技术思考和细节。

大多数 LLM(大型语言模型)是基于自然语言和源代码文本进行训练的,并没有考虑自然语言和代码之间的区别。代码有其结构、严格的语法和一个可以确定性解析它的编译器, 这些特性是可以被利用的。

一些研究已经尝试对模型进行微调,使用像 AST(抽象语法树)、CST(具体语法树)、数据流、控制流甚至程序执行等结构化代码表示。然而, 基于这些模型的AI调优将需要时间(和计算能力!)。此外,这些树缺乏关于代码的语义数据,例如类型分配,而这些数据对于准确的代码库搜索至关重要。

目前,像聊天机器人这样的业务应用使用了一种称为检索增强生成(RAG)的技术来增强LLM的训练。RAG 通过使用嵌入从相关外部来源获取数据, 来提高生成 AI 模型的准确性和可靠性,指导模型的决策过程。向量允许我们为模型提供上下文,包括它未曾接受过训练的数据,以及比实时 IDE 上下文窗口提供的更多文本。

在处理大型代码库时,我们也需要一种方法来从用户的代码库中检索相关数据作为上下文,并将其与查询一起输入 LLM。幸运的是,通过 OpenRewrite 自动重构开源项目, 我们获得了一种新的代码表示形式——无损语义树(LST),它包括类型分配和其他元数据。这种全保真度的代码表示形式是准确搜索和转换代码的基础——它可以像嵌入一样在自然语言文本中发挥作用。 此外,Moderne 平台将 LST 序列化到磁盘,使其水平扩展,从而将重构工作从单一仓库模式扩展到多仓库模式。

Moderne 平台通过聚合 LST,使我们能够查询大型代码库,并将结果提供给LLM进行查询或生成。然后,我们可以使用我们的100%准确的重构系统验证 LLM 的建议。

总而言之,对于代码处理,Moderne 可以利用 LST 为 LLM 提供高度相关的上下文,这些LST是你代码的极其丰富的数据表示。我们使用开源 LLM 在我们的平台上安全地部署这一解决方案, 确保没有代码离开这个环境。此外,通过我们的平台,我们可以有效地测试并选择适合特定任务的最佳 LLM。

在OpenRewrite规则基础上的AI LLM集成

Moderne 平台在预构建和缓存的 LST(无损语义树)上运行 OpenRewrite 规则(或程序),以搜索和转换代码。这使我们能够在多个代码库中执行规则,提供近乎实时的反馈,以进行实时代码分析。

在创建规则时,提供了许多声明性格式以便于使用,但用户也可以开发自定义编程规则以获得最大灵活性。还可以实现多种类型的集成,例如自定义的 OpenRewrite 规则。 一个这样的例子是 LaunchDarkly 特性标志移除,它调用 LaunchDarkly 来识别未使用的特性标志,从代码库中移除特性标志下的功能,然后再次调用 LaunchDarkly 来删除未使用的特性标志。 一个规则还可以包装和执行其他工具,例如我们在JavaScript codemods集成中的应用。

LLM(大型语言模型)是我们可以集成到规则中的另一个重要工具,以支持新的和有趣的用例。我们专注于可以在 CPU 上运行的开源专用 LLM, 以在Moderne 平台内实现最大操作安全性和效率。这使我们能够在与规则处理 LST 代码表示形式的相同基于 CPU 的工作节点上配置这些模型。 通过测试和评估各种从Hugging Face下载的模型,我们可以识别最佳模型,并随着每天新模型的到来不断迭代选择。模型的选择可能会影响任务的准确和快速完成与否。

当规则在工作节点上运行时,它可以在LST中搜索所需的数据,将其传递给适当的LLM,并接收响应。LST仅将需要评估或转换的部分发送给模型。规则然后将LLM响应插入回LST中。 Moderne平台生成差异供开发者审查,并提交回源代码管理(SCM),确保模型以精准的方式完成其任务。参见图1中的流程。

Bloop

State of Mainframe Modernization

转换 HumanEval 数据集

构建评估工具:COBOLEval

       IDENTIFICATION DIVISION.
       PROGRAM-ID. HAS-CLOSE-ELEMENTS.

       ENVIRONMENT DIVISION.

       INPUT-OUTPUT SECTION.

       DATA DIVISION.

       LINKAGE SECTION.

       01 LINKED-ITEMS.
           05 L-NUMBERS OCCURS 100 TIMES INDEXED BY NI COMP-2.
           05 L-THRESHOLD COMP-2.
           05 RESULT PIC 9.

      * Check if in given list of numbers, are any two numbers closer to each other than
      * given threshold.
      * >>> has_close_elements([1.0, 2.0, 3.0], 0.5)
      * False
      * >>> has_close_elements([1.0, 2.8, 3.0, 4.0, 5.0, 2.0], 0.3)
      * True
      *

      * Complete the WORKING-STORAGE SECTION and the PROCEDURE DIVISION
      * Store the result in the RESULT variable and mark the end of your program with END PROGRAM

       WORKING-STORAGE SECTION.

SourceGraph Cody示例

资料来源:A simpler way to understand legacy code

这篇文章介绍了构建遗留系统重构的过程和策略,并提供了一些实用工具来帮助开发人员理解和改进遗留代码。

主要流程和策略如下:

  1. 评估代码库:
    • 设置开发环境并运行代码以确保其按预期工作。
    • 使用代码静态检查工具(如ESLint或Pylint)来识别语法错误和潜在问题。
    • 使用依赖关系分析工具和架构可视化工具来了解项目的依赖关系和结构。
  2. 文档和注释:
    • 利用现有的文档和注释来获取代码的原始目的、设计决策和潜在问题的洞察。
    • 对缺乏文档的遗留系统进行文档补充和注释更新。
  3. 代码分析工具:
    • 使用静态分析工具(如SonarQube、PMD、CAST)来识别代码问题、代码异味和安全漏洞。
    • 这些工具还能揭示代码依赖关系和结构,帮助开发人员确定重构的优先级。
  4. 版本控制历史:
    • 利用版本控制系统(如Git)来理解代码库的历史,通过分析提交日志来追踪代码的变更。
    • 使用git blamegit log命令来了解每行代码的最后修改情况及其原因。
  5. 重构和清理:
    • 在不改变外部行为的前提下对代码进行重构,以提高代码的可维护性和可读性。
    • 采用小规模、可管理的更改,使用特性分支并持续测试代码,以验证重构未影响功能。
  6. 测试和验证:
    • 编写单元测试、集成测试和端到端测试来验证更改,防止回归问题。
    • 在没有测试的遗留代码上编写测试,以确保代码可靠性。

使用Cody的辅助工具:

Cody是一款AI编程助手,旨在帮助开发人员理解、编写、审查和重构代码,并加速代码生成和软件开发。它的主要功能包括:

  • 自动完成:利用大语言模型(LLM)提供代码预测和建议,支持多种编程语言。
  • 聊天功能:回答与代码相关的技术问题,并提供上下文答案。
  • 命令功能:运行预定义操作并创建自定义命令以加速日常编码任务。

通过这些功能,Cody可以帮助开发人员理解遗留代码结构,识别潜在问题,并提出改进建议。

使用Cody的实际示例:

  1. 重构代码:Cody可以识别代码异味并建议改进。
  2. 编写单元测试:Cody可以生成单元测试代码,帮助验证代码的预期行为。
  3. 生成文档:Cody可以自动生成代码文档,帮助未来的协作者理解代码。

总结:

通过评估代码库、利用文档、使用代码分析工具、理解版本控制历史、谨慎重构和全面测试,开发人员可以有效地理解和改进遗留代码。AI编程助手如Cody能够进一步简化这些过程,提供有价值的见解和自动化支持,使处理遗留系统变得更容易和高效。

AI 辅助软件工程:遗留系统与技术栈迁移

示例

Google

Accelerating code migrations with AI

多年来,谷歌一直使用专门的基础设施来执行复杂的代码迁移。该基础设施使用静态分析和如 KytheCode Search 等工具来发现需要更改的位置及其依赖关系。然后使用如 ClangMR (Clang’s refactoring engine)等工具进行更改。

这种方法对结构统一且边缘情况有限的更改效果很好。然而,当迁移具有复杂结构的代码时,静态分析和简单的迁移脚本会遇到限制——例如,改变接口及其在多个组件及其依赖中的使用,或更新其测试。

我们将迁移过程概念性地分为三个阶段:

  • 确定需要修改的代码库位置
  • 编辑生成和验证
  • 更改审查和发布

虽然这些阶段中的每一个都受益于 AI,我们主要关注第 2 阶段。

为了生成和验证代码更改,我们利用了在谷歌内部代码和数据上微调过的 Gemini 模型版本。

每次迁移需要以下输入:

  • 一组文件和预期更改的位置:路径 + 文件中的行号
  • 一到两个描述更改的提示
  • [可选] 少量示例,以确定文件是否确实需要迁移

多阶段代码迁移过程的示例执行。

用户提供的文件位置通过预先存在的静态工具和人工输入的组合进行收集。我们的迁移工具包会自动扩展这组文件,添加其他相关文件,包括:测试文件、接口文件和其他依赖项。 这一步骤尚未由 AI 驱动,但使用了符号交叉引用信息。

在许多情况下,用户提供的迁移文件集并不完美。由于过滤输入列表可能很繁琐,一些文件可能已经部分或完全迁移。因此,为了避免冗余更改或在编辑生成过程中混淆模型, 我们提供了少量示例,并要求模型预测文件是否需要迁移。

编辑生成和验证步骤是我们发现自动系统最有益的地方。我们的模型在谷歌的单体代码库和流程数据上按照 DIDACT 方法进行了训练。在推理时, 我们用自然语言指令以及模型的一般指令对每一行预计需要更改的地方进行标注。在每次模型查询中,输入上下文可以包含一个或多个相关文件。

模型然后预测文件之间的差异(diff),并且可以更改相关部分,以确保最终代码正确。

案例研究:将整数从 32 位迁移到 64 位

随着谷歌代码库及其产品的演进,以前做出的假设(有时是在十多年前)已不再成立。例如,谷歌广告有数十种用于处理用户、商户、广告系列等的数字唯一“ID”类型, 这些ID最初定义为32位整数。但随着ID数量的增长,我们预计它们会比预期更早地溢出32位容量。

这一认识促使我们进行了将这些ID迁移到64位整数的重大工作。该项目困难重重,原因包括:

  • 在数千个文件中的数万个位置使用这些ID。
  • 如果每个团队都自己处理迁移,跟踪所有涉及团队的更改将非常困难。
  • 这些ID通常定义为通用数字(C++中的int32_t或Java中的Integer),不是唯一的、易于搜索的类型,这使得通过静态工具查找它们的过程变得复杂。
  • 需要在多个文件中考虑类接口的变化。
  • 需要更新测试以验证64位ID是否被正确处理。

如果手动完成,这项工作预计需要许多年的软件工程时间。 为了加速工作,我们使用了 AI 迁移工具,并制定了以下工作流程:

  1. 一位专家工程师识别出他们想迁移的 ID,并使用 Code Search、Kythe 和自定义脚本的组合,识别出需要迁移的(相对紧凑的)文件和位置超集。
  2. 迁移工具包自动运行并生成经过验证的更改,这些更改仅包含通过单元测试的代码。某些测试本身也会更新以反映新的现实。
  3. 工程师快速检查更改,并可能更新模型失败或出错的文件。然后,这些更改会被分片并发送给多个负责受更改影响的代码库部分的审查员。

请注意,内部代码库中使用的ID已经应用了适当的隐私保护。在将它们迁移到新类型时,模型不会更改或公开这些 ID,因此所有隐私保护措施将保持不变。

在这项工作流中,我们发现80%的代码修改是在AI的帮助下完成的,其余的是由人工完成的。根据执行迁移的工程师报告,总迁移时间减少了估计 50%。通信开销显著减少, 因为一个工程师可以生成所有必要的更改。工程师仍然需要花时间分析需要更改的文件和进行审查。我们发现,在 Java 文件中, 我们的模型以 91% 的准确率预测了需要编辑的文件。

该工具包已经用于在此迁移和其他迁移中创建了数百个更改列表。平均而言,我们成功地将超过 75% 的 AI 生成的字符更改合并到单体代码库中。

Ebay:定期维护和升级基础设施

Cutting Through the Noise: Three Things We've Learned About Generative AI and Developer Productivity

现有的开源大型语言模型有时会达到生产力的上限;毕竟,从一个不包含我们内部数据的模型中,我们能学到的东西是有限的。因此,第二条路径是使用我们组织预处理后的数据对开源的LLMs进行后期训练和微调。

在这个练习中,我们使用了 Code Llama 13B 作为基础 LLM,不过如果有需要,也可以轻松替换成其他模型。为了看看后期训练和微调的现有 LLM 效果如何, 我们创建了一个我们称之为 eBayCoder 的模型:这是一个基于eBay代码库和相关文档训练的Code Llama。

那么效果如何呢?我们发现,eBayCoder 能够显著简化一些之前劳动密集型且耗时的任务。例如,软件维护在所有技术组织中都至关重要。和其他大型公司一样,eBay 也有自己基于开源软件构建的基础库和框架,覆盖服务器、消息队列、批处理作业、iOS 和 Android 等。这些系统需要定期升级, 以改进开发人员的工作体验并解决安全漏洞(例如升级到最新的 Spring 或 Spring Boot 版本)。这种工作量视当前应用栈的版本而定,有时甚至会非常庞大。 即使使用eBay现有的迁移工具,我们仍需投入大量工程资源进行软件维护。而这是我们认为微调后的LLM在短期内已经能够产生巨大影响的一个领域。

对于像 eBay 这样庞大且多样的代码库,我们有时也会遇到一个问题,即现有的商业LLM产品只能访问与当前问题直接相关的数据和代码,通常是周围的文件、 当前的代码库以及一些依赖库。它可能无法察觉到其他团队维护的不同内部服务或非依赖库中提供的相同功能。这往往导致大量的代码重复。 但一个微调后的LLM可以访问我们希望的尽可能多的上下文,从而有可能减少代码重复的数量。

Amazon 遗留基础设施改造:Code Transformation

Upgrade your Java applications with Amazon Q Code Transformation (preview)

许多组织面临维护关键遗留 Java 应用程序的挑战,这些应用程序由于框架过时、代码无文档和安全漏洞而变得难以维护。现代化这些应用程序是必要且具有挑战性的任务。Amazon Q Developer 简化并加速了这一过程。

Java 8 迁移到 Java 17

Code Transform

应用程序的端到端升级包括以下三个步骤:

  1. 识别和分析应用程序 – 代码会被复制到云中的托管环境,并根据代码库中的指示设置构建过程。在此阶段,确定需要升级的组件。
  2. 创建转换计划 – 分析代码以创建转换计划,列出 Amazon Q Code Transformation 将采取的步骤,包括更新依赖项、构建升级后的代码,并在升级过程中逐步修复遇到的构建错误。
  3. 代码生成、构建测试和最终化 – 按照转换计划逐步更新现有代码和配置文件,必要时生成新文件,使用提供的测试进行构建验证,并修复在失败的构建中发现的问题。

Code Transform

要转换代码,Amazon Q Developer Agent会生成一个转换计划,用于升级项目的代码语言版本。转换代码后,它会提供一个转换总结和文件差异视图,以便您在接受更改之前进行审查。以下部分详细介绍了Amazon Q如何执行转换。

构建代码并创建转换计划

要开始转换代码,Amazon Q会在本地构建您的项目,并生成一个构建工件,其中包含源代码、项目依赖项和构建日志。此构建工件必须小于1 GB,Amazon Q才能转换代码。

生成构建工件后,Amazon Q会在一个安全的构建环境中构建代码,并创建一个转换计划,该计划针对您正在升级的项目或模块进行定制。转换计划概述了Amazon Q将尝试进行的具体更改,包括新的依赖版本、主要代码更改以及对废弃代码的建议替换。这些更改基于对您代码的初步构建,可能会在转换过程中有所变化。

转换代码

为了转换代码,Amazon Q会根据转换计划中的建议尝试升级代码。在进行更改时,它会重新构建并运行源代码中的现有单元测试,以逐步修复遇到的错误。

在升级代码时,Amazon Q会尝试进行以下更改:

  • 将流行的库和框架升级到与Java 17兼容的版本,包括更新Spring、Spring Boot、JUnit、JakartaEE、Mockito、Hibernate和Log4j到其最新的主要版本。
  • 根据Java 17的推荐更新已废弃的代码组件。
审查转换总结并接受更改

转换完成后,Amazon Q会提供一个转换总结,详细说明其所做的更改,包括最终构建的状态,指示整个项目是否已升级。您还可以查看构建日志摘要,以了解阻止Amazon Q在升级版本中构建代码的任何问题。

转换总结还包括转换计划中建议的更改与Amazon Q最终实际进行的更改之间的差异,以及任何不在原始计划中的额外更改。

在审查转换总结后,您可以在文件差异视图中查看Amazon Q建议的更改。在您接受更改之前,Amazon Q建议的代码更改不会影响当前的项目文件。转换后的代码将在转换完成后最多保留24小时。

使用 Amazon Q Developer 的现代化过程

  1. 升级 Java 版本:
    • 从Java 8 升级到Java 17,以提高性能、安全性并利用新功能。
    • Amazon Q Developer代码转换代理通过分析代码、生成转换计划并更新框架和库以兼容Java 17来自动化这一过程。
  2. 减少技术债务:
    • 识别并解决代码库中的技术债务,以提高代码质量和可维护性。
    • 使用 Amazon Q Developer 生成技术债务问题列表并提出改进建议。
    • 实施建议,如改进日志记录和模块化,以减少技术债务。
  3. 云原生部署:
    • 将应用程序迁移到云原生架构并部署到 AWS。
    • 步骤包括将应用程序容器化,使用 Amazon Elastic Container Registry(ECR),在 AWS Fargate 上部署到 Amazon Elastic Container Service(ECS),并设置 Amazon CloudWatch 进行监控。
    • Amazon Q Developer 帮助生成用于容器化的 Dockerfile 和用于基础设施部署的 CloudFormation 模板。

AI 辅助场景:构建团队 AI

Team AI 是一个加速器,旨在协助团队构建轻量级 AIGC 辅助效能提升机制。它可充当任务助手,以简化和加快日常事务中频繁执行的任务;它也可充当知识增强工具,协助团队进行头脑风暴,并更早地在交付过程中发现问题;此外,它还可以充当团队的"合作伙伴",将团队的约定规范与生成式AI相融合。

在这篇文章里,我将介绍我对于 Team AI 的理解,以及如何构建 Team AI,加速团队的研发效率。

为什么我们需要 Team AI?

不同的团队,可能需要根据其特定需求和业务领域,定制自己的 AIGC 助手。作为一个曾经担任过后端、移动端、前端的 Tech Lead,我深深地理解这一样。特别是不同类型的团队,对于 AIGC 所需要提升的点是大为不同的。

诸如,我们在 Chocolate Factory 构建的自然语言生成 UI 代码的示例里,是会根据团队的规范、组件库、业务信息等来生成 UI 代码的。也因此,在不同的场景之下,我们所需要的这种能力也是颇为不同的。哪怕是在金融企业里,不同部门所处的业务领域也会有所差异的。

而会影响构建统一 AIGC 的原因,还包含了(由 ChatGPT 辅助生成):

  • 不同类型的任务和工作流程。一些团队可能需要处理大量数据分析,而其他团队可能更关注客户服务或生产流程。
  • 团队规模和组成。不同团队的规模和成员组成也会有所不同。一些团队可能由少数成员组成,而其他团队可能是大规模的企业部门。
  • 不同的战略目标和优先级。一些团队可能更关注成本削减,而其他团队可能更关注创新和增长。
  • ……

而从另外一个层面来讲,我们在团队拓扑中所定义的不同类型的团队,也会在使用 Team AI 场景上有所差异。诸如于,我们更建议赋能型团队、平台型平台,应该拥有自己的 AIGC 知识聊天助手。

什么是 Team AI?

让我们再回到先前的定义:

Team AI 是一个加速器,旨在协助团队构建轻量级 AIGC 辅助效能提升机制。它可充当任务助手,以简化和加快日常事务中频繁执行的任务;它也可充当知识增强工具,协助团队进行头脑风暴,并更早地在交付过程中发现问题;此外,它还可以充当团队的"合作伙伴",将团队的约定规范与生成式AI相融合。

尽管我们落地 Team AI 的场景更多的是在软件研发上,但是结合我们的 AIGC 应用场景来看,Team AI 可以适用于所有的团队 —— 诸如营销团队,可以构建用户画像,根据用户画像来生成不同的营销方案、营销内容等等。

Team AI 能做什么?

我们设计 Team AI 的初衷是,构建适用于团队轻量级、高频/高价值场景下的 AI 辅助工具。

轻量级意味着我们能快速构建和应用我们的 Prompt 或者 AIGC 功能,诸如于 AutoDev 的 Team Prompts 功能,可以直接读取项目中的 promtp,并作为 IDE 功能的一部分。

高频/高价值场景。高频场景只是一个相对的值,只要一个任任务相对频繁或者相对比较繁杂,我们就可以考虑结合 AIGC 来辅助提升。

而团队就意味着,要由团队协作来完成自己的 AI 辅助工具。

构建 Team AI 所需要的能力

它需要什么样的能力:

  • 快速访问不同大模型的能力。除了文本、图像、音频等的大模型,同一类型的模型在能力上也是有所差异的。
  • 团队共享的 prompt 空间。根据不同团队的组织目标,创建、存储和组织自定义的 prompt 库。
  • 团队协同的 prompt 设计。在内部持续优化和完善提示词,允许存在个人的分支,以确保在内部更好的交流、分享。
  • 知识辅助增强能力。即内部可以快速上传文档,并从中检索出关键信息,以生成关键的洞见信息。

应对于这些需求,从我们现有的探索来看,有三种方式能构建我们的 Team AI。

如何因地制宜构建 Team AI?

在今天,构建 Team AI 已经变得非常的简单,从我们的案例里找到了三种方式:结合现有工具、定制端到端应用、基于平台能力构建。

1. 轻量级方式:结合现有工具

从 Team AI 的角度来说,最简单的方式是结合已有的工具。在有了这个思考之后,我们在 AutoDev 里构建了 Team Prompts。它可以集成到代码库中,以用便于:

  • 在团队里,共享你的 prompt,而不再是个性化的配置。
  • 可以在各自的团队里分享自己的 AI 经验。
  • 不再需要定制更多的 IDE 需求,只需要提供接口能力即可。

那么,对于软件开发团队来说,它就是一种非常简单的 Team AI 方式。当然了,市面上也有非常多的这一类的工具。

2. 定制化 Team AI:构建端到端应用

如开头所说,Team AI 从已经构建的内部工具作为起点。它与现有工具相比,更适合于定制团队所需要的端到端方案。

诸如于,在我们的 Team AI 基础代码库中,提供的 SQL 生成示例里,你需要填入一些基础的 SQL 信息。而在多数场景下,我们可以直接使用对应的 Java 对象,或者结合现有的数据库表。在具备了更准确上文的情况下,生成的内容质量更加准确,那么对于开发团队的提升就更高。

而在我们具备了 LLMOps 平台之后,要构建这一类的应用就更加简单。

3. 基于平台能力:快速可复用的 AI

今天,我们可以看到有大量的组织构建了自己 LLMOps 平台,并且也有一系列的开源平台,诸如 Dify 等。当然了,我们内部也有一个类型的 LLMOps 平台:GluonMeson,正在计划开源中。

回到这些平台来说,它们都能快速创建应用、生成式应用、会话式应用等等。围绕于这些能力(诸如于 API、多模态),我们能快速构建属于团队的 Team AI。

其它

除此,我们也可以从搜索引擎中发现,一些 AI 初创公司也在这个点上发力。通过构建经典的 Team Workspace 方式,来提供这种协作能力,并将不同能力集成在一起。

总结

最后,让 ChatGPT 来总结这篇文章:

Team AI 是一个旨在协助团队提高工作效率的项目,通过简化任务、知识增强和合作伙伴支持。它可以根据不同团队的需求和应用领域,采用不同的构建方式,从结合现有工具到定制化端到端应用,以加速团队的工作流程。 Team AI 的关键目标是为高频、高价值的场景提供轻量级AI辅助工具,以满足团队的特定需求。

编码智能体辅助软件工程

形态

16x

16x Prompt 示例:

Webwright : Shell 增强

graph TD
    A[User] -->|Enters command| B[Webwright Shell]
    B -->|Processes command| E{OpenAI or Anthropic?}
    E -->|OpenAI| F[OpenAI API]
    E -->|Anthropic| G[Anthropic API]
    F -->|Response| H[Process AI Response]
    G -->|Response| H
    H <-->|Query/Update| L[(Vector Store)]
    H <-->|Query/Update| M[(Set Store)]
    H -->|Generate Code/App| I[Code/Application Output]
    H -->|Execute Function| J[Function Execution]
    J -->|Result| K[Process Function Result]
    K -->|Update Context| B
    I -->|Display to User| A
    B <-->|API Calls| N[mitta.ai API]
    N -->|Document Processing| O[Process Documents]
    N -->|Web Crawling| P[Crawl Websites]
    N -->|Other Functionality| Q[...]

Auto Wiki

https://wiki.mutable.ai/

Auto Wiki v2

CrawAI

https://github.com/crewAIInc/crewAI

  • 基于角色的智能体设计:可定制具有特定角色、目标和工具的智能体。
  • 自主智能体间委托:智能体能够自主地委托任务并在彼此间进行询问,从而提高问题解决效率。
  • 灵活的任务管理:定义任务并使用可定制工具,动态分配给智能体。
  • 流程驱动:目前支持顺序任务执行和分层流程,正在开发更复杂的流程,如共识和自主流程。
  • 将输出保存为文件:可以保存单个任务的输出为文件,以便后续使用。
  • 输出解析为 Pydantic 或 JSON:如需,可将单个任务的输出解析为 Pydantic 模型或 JSON。
  • 兼容开源模型:可使用 Open AI 或开源模型运行您的团队。参考“连接 crewAI 到 LLMs”页面,了解如何配置智能体与模型之间的连接,甚至包括本地运行的模型!

示例

Builder.io

Introducing Micro Agent: An (Actually Reliable) AI Coding Agent

Micro Agent

Micro Agent 是一种生成式 AI 工具,通过聚焦于特定任务并通过单元测试提供清晰的确定性反馈来创建代码。以下是其工作流程的细分:

  1. 描述你的函数:你提供一个关于所需函数的自然语言描述。
  2. AI 生成测试:基于你的描述,Micro Agent 创建定义函数预期行为的单元测试,包括多个输入输出场景。
  3. AI 编写代码:使用大型语言模型(LLMs)的能力,Micro Agent 编写代码(支持 JavaScript、TypeScript、Python 或其他语言)以通过生成的测试。
  4. 自动迭代:如果初始代码未能通过任何测试,Micro Agent 会反复编辑源代码并重新运行测试,直到所有测试都通过。这确保了最终代码符合指定要求。

主要优势

  • 更高的保证:生成的代码更可靠,能够满足指定的要求,因为它通过了确定性的测试。
  • 简化的开发过程:自动化的迭代过程有助于高效地创建高质量代码,节省时间并提高结果的信心。

Codium: Cover-Agent && PR-Agent

CodiumAI Cover Agent aims to help efficiently increasing code coverage, by automatically generating qualified tests to enhance existing test suites.

Below is the roadmap of planned features, with the current implementation status:

  • Automatically generates unit tests for your software projects, utilizing advanced AI models to ensure comprehensive test coverage and quality assurance. (similar to Meta)
    • Being able to generate tests for different programming languages
    • Being able to deal with a large variety of testing scenarios
    • Generate a behavior analysis for the code under test, and generate tests accordingly
    • Check test flakiness, e.g. by running 5 times as suggested by TestGen-LLM
  • Cover more test generation pains
    • Generate new tests that are focused on the PR changeset
    • Run over an entire repo/code-base and attempt to enhance all existing test suites
  • Improve usability
    • Connectors for GitHub Actions, Jenkins, CircleCI, Travis CI, and more
    • Integrate into databases, APIs, OpenTelemetry and other sources of data to extract relevant i/o for the test generation
    • Add a setting file

Factory.ai:化繁为简

软件开发包含一系列的任务及子任务,诸如于:

  • 依赖编码规范、框架知识、架构设计、安全指标等进行代码编写

https://www.factory.ai/ 示例

如何结合 AI 更好进行知识管理,简化为项目、编码、测试、检视、文档等步骤,实现从想法到产品的快速迭代?

简化

Cursor:Shadow Workspace

Shadow Workspace: Iterating on Code in the Background

Shadow Workspace 设计标准。我们希望 Shadow Workspace 能实现以下目标:

  1. LSP 可用性:AI 应该能够看到他们更改后的 lint 提示,能够跳转到定义,并且更广泛地与语言服务器协议 (LSP) 的所有部分进行交互。
  2. 可运行性:AI 应该能够运行他们的代码并查看输出。

我们最初专注于 LSP 可用性。 这些目标应满足以下要求:

  1. 独立性:用户的编码体验必须不受影响。
  2. 隐私性:用户的代码应是安全的(例如,所有代码都保存在本地)。
  3. 并发性:多个 AI 应该能够同时进行工作。
  4. 通用性:应适用于所有语言和所有工作区设置。
  5. 可维护性:代码应尽可能少且易于隔离。
  6. 速度:任何地方都不应有分钟级的延迟,并且应有足够的吞吐量以支持数百个 AI 分支。

其中许多反映了为超过十万用户构建代码编辑器的现实情况,我们确实不希望对任何人的编码体验产生负面影响。

问题:

问题

实现:

Shadow Workspace

  1. AI 提议对文件进行编辑。
  2. 编辑从普通窗口的渲染进程发送到其扩展宿主,然后传送到 Shadow window 的扩展宿主,最后传送到 Shadow window 的渲染进程。
  3. 编辑在 Shadow window 中应用, Shadow window是隐藏且独立于用户的,所有 lint 提示都以相同的方式发送回来。
  4. AI 接收到 lint 提示,并决定如何进行迭代。

shadow_workspace.proto

https://gist.github.com/arvid220u/b976c87c7ec9f6f66595dc0ebc0f07d6

syntax = "proto3";

package aiserver.v1;
option go_package = "github.com/anysphere/everysphere/schema/aiserver/v1";

service ShadowWorkspaceService {
	rpc GetLintsForChange(GetLintsForChangeRequest) returns (GetLintsForChangeResponse) {}
  rpc ShadowHealthCheck(ShadowHealthCheckRequest) returns (ShadowHealthCheckResponse) {}
}

message ShadowHealthCheckRequest {}

message ShadowHealthCheckResponse {}

// only lints in the supplied files are returned
//
// note that this only returns lints that were changed! unless `get_all_lints_not_just_delta_lints_for_range_in_final_model` is set
message GetLintsForChangeRequest {
  repeated File files = 1;

  message File {
    string relative_workspace_path = 1;

    // the "change" we are getting lints for is the implicit delta between `initial_content` and `final_content`
    string initial_content = 2;
    string final_content = 3;

    // for any lints in the final model that are inside one of these ranges, we return it regardless of whether it existed in the initial model too
    optional RangeCollection get_all_lints_not_just_delta_lints_for_ranges_in_final_model = 4;

    message RangeCollection {
      repeated IRange ranges = 1;
    }

    // simply corresponds to vscode's irange
    message IRange {
      // 1-indexed
      int32 start_line_number = 1;
      // 1-indexed
      int32 start_column = 2;
      // 1-indexed
      // inclusive
      int32 end_line_number = 3;
      // 1-indexed
      int32 end_column = 4;
    }
  }

  // quick fixes will be returned for each lint. potentially a little bit slower
  bool include_quick_fixes = 2;

  // if a new file is not created, some tools will report inaccurate or incomplete lints (e.g., the typescript language server won't properly detect which tsconfig is the right one)
  // the temporarily created file will have a .shadowworkspace-uuid.ts extension, to reduce the chance of conflicts
  // the hope is that it won't affect the user, but it may, so therefore this is off by default for now
  // once we have a proper proxy folder structure, then this should hopefully be obsolete
  // WARNING: this can cause problems for the user!!! (our yarn watch breaks when new files are added and deleted, for example)
  // do not run this for real users! before we have the proxy folder set up
  bool do_not_use_in_prod_new_files_should_be_temporarily_created_for_increased_accuracy = 3;

}

message GetLintsForChangeResponse {
  repeated Lint lints = 1;
  message Lint {
    string message = 1;
    string severity = 2;
    string relative_workspace_path = 3;
    // the position refers to the position in the `final_content` model
    int32 start_line_number_one_indexed = 4;
    int32 start_column_one_indexed = 5;
    int32 end_line_number_inclusive_one_indexed = 6;
    int32 end_column_one_indexed = 7;

    message QuickFix {
      message Edit {
        string relative_workspace_path = 1;
        string text = 2;
        int32 start_line_number_one_indexed = 3;
        int32 start_column_one_indexed = 4;
        int32 end_line_number_inclusive_one_indexed = 5;
        int32 end_column_one_indexed = 6;
      }
      string message = 1;
      string kind = 2;
      bool is_preferred = 3;
      // TODO: this edit can also be a file edit in vscode! currently, we ignore those, and only include text edits
      repeated Edit edits = 4;
    }
    // only included if `include_quick_fixes` is true
    repeated QuickFix quick_fixes = 9;
  }
}

其它

相关材料

开源自主 AI Agent 汇总 伴随 LLM 的快速发展,以 LLM 为大脑的 Agents 能力也越来越强,它们能结合规划、记忆和工具使用,来让 LLM 具备丰富的行动能力。

关于 Autonomous Agents LLM Powered Autonomous Agents via Lilian Weng https://lilianweng.github.io/posts/2023-06-23-agent/… 今天我们一起看看都有哪些开源 Agent 项目值得参考 以下是整理好的表格:

项目名称开发者Stars描述链接
AutoGPT@SigGravitas164k基于 LLM 的通用 Agent 框架,可以自主完成简单任务。四个重要组件:Agent、Benchmark、Forge、Frontend。AutoGPT
BabyAGI@yoheinakajima19.7kBabyAGI 能够根据给定的目标生成并执行任务,运用了来自 OpenAI、Pinecone、LangChain 和 Chroma 的前沿技术。BabyAGI
SuperAGI@_superAGI15kSuperAGI 框架提供了一个开放源代码的平台,用于创建、控制与执行 Autonomous Agents,增强 Agents 的功能性。SuperAGI
AutoGen@pyautogen28.3kAutoGen 是一个开源编程框架,用于构建 AI Agents 并促进多个 Agents 间的协作以解决任务。AutoGen
MetaGPT@AlexanderWu041.6kMetaGPT 是一个 Multi-Agents 框架,分配不同的角色给 LLM,形成一个协同实体,以应对复杂的任务。MetaGPT
CamelAI@CamelAIOrg4.8kCAMEL 是一个专为研究自主与交流型 Agent 而设计的开源库,推进领域研究多种类型的 Agents、任务、提示、模型和模拟环境。CamelAI
Dify@dify_ai37.1kDify 是一个开源 LLM 应用开发平台,结合 AI 工作流、RAG 管道、Agent 能力、模型管理、可观察性功能等。Dify
CrewAI@crewAIInc17.1k用于协调角色扮演、Autonomous Agents 的尖端框架,促进协作智能,解决复杂任务。CrewAI
Botpress@getbotpress12.2kBotpress 构建由 OpenAI GPT 提供支持的聊天机器人和助手的终极平台。Botpress
AgentGPT@ReworkdAI30.6kAgentGPT 允许配置和部署 Autonomous Agents,自定义 AI,实现任何目标。AgentGPT

编码智能体:编码智能体基础设施

Embedding 介绍

AI Concepts

AI概念

了解如何使用向量技术构建AI应用

向量技术是构建AI应用的核心组成部分。本文将介绍向量及其生成、使用和在Postgres中的存储方式。

什么是向量?

在处理非结构化数据时,一个常见的目标是将其转化为更易于分析和检索的结构化格式。这种转化可以通过“向量”实现,向量是包含一组浮点数的向量,代表数据的特征或维度。例如,像“牛跳过月亮”这样的句子可以表示为一个类似这样的向量:[0.5, 0.3, 0.1]。

向量的优点在于它们可以衡量不同文本片段之间的相似度。通过计算两个向量之间的距离,我们可以评估它们的相关性——距离越小,相似度越大,反之亦然。这一特性特别有用,因为它使向量能够捕捉文本的内在含义。

例如,考虑以下三句话:

  1. 句子1:“牛跳过月亮。”
  2. 句子2:“牛跳跃在天体之上。”
  3. 句子3:“我喜欢吃煎饼。”

你可以按照以下步骤确定最相似的句子:

  1. 为每个句子生成向量。假设这些值代表实际向量:
  • 句子1的向量 → [0.5, 0.3, 0.1]
  • 句子2的向量 → [0.6, 0.29, 0.12]
  • 句子3的向量 → [0.1, -0.2, 0.4]
  1. 计算所有向量对(1&2, 2&3, 1&3)之间的距离。

  2. 确定距离最短的向量对。

当我们应用这一过程时,句子1和句子2这两句都涉及跳跃的牛,根据距离计算,它们可能会被识别为最相关的。

向量相似性搜索

将数据转化为向量并计算一个或多个项目之间的相似性被称为向量搜索或相似性搜索。这个过程有广泛的应用,包括:

  • 信息检索:通过将用户查询表示为向量,我们可以基于查询背后的意义执行更准确的搜索,从而检索到更相关的信息。
  • 自然语言处理:向量捕捉文本的本质,使其成为文本分类和情感分析等任务的优秀工具。
  • 推荐系统:利用向量相似性,我们可以推荐与给定项目相似的项目,无论是电影、产品、书籍等。这个技术允许我们创建更个性化和相关的推荐。
  • 异常检测:通过确定数据集中项目之间的相似性,我们可以识别出不符合模式的异常项。这在许多领域中都至关重要,从网络安全到质量控制。

距离度量

向量相似性搜索通过计算数据点之间的距离来衡量它们的相似性。计算数据点之间的距离有助于我们理解它们之间的关系。距离可以通过不同的度量方式计算。一些常见的距离度量包括:

  • 欧几里得距离(L2):通常被称为“普通”距离,用尺子测量的距离。
  • 曼哈顿距离(L1):也称为“出租车”或“城市街区”距离。
  • 余弦距离:计算两个向量之间角度的余弦。

pgvector扩展还支持其他距离度量,如汉明距离和雅卡尔距离。

不同的距离度量适用于不同的任务,具体取决于数据的性质和你关注的特定关系。例如,余弦相似性常用于文本分析。

生成向量

生成向量的一种常见方法是使用LLM API,例如OpenAI的向量API。该API允许你将文本字符串输入到API端点,然后返回相应的向量。“牛跳过月亮”是一个具有3个维度的简单示例。大多数向量模型生成的向量具有更多的维度。OpenAI最新且性能最好的向量模型text-embedding-3-small和text-embedding-3-large默认生成1536和3072维度的向量。

以下是如何使用OpenAI的text-embedding-3-small模型生成向量的示例:

curl https://api.openai.com/v1/embeddings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "input": "Your text string goes here",
    "model": "text-embedding-3-small"
  }'

注意:运行上述命令需要一个OpenAI API密钥,必须从OpenAI获取。

成功执行后,你将收到类似以下的响应:

{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "index": 0,
      "embedding": [
        -0.006929283495992422,
        -0.005336422007530928,
        ... (为了简洁省略)
        -4.547132266452536e-05,
        -0.024047505110502243
      ],
    }
  ],
  "model": "text-embedding-3-small",
  "usage": {
    "prompt_tokens": 5,
    "total_tokens": 5
  }
}

要了解更多关于OpenAI向量的信息,请参见向量。 这里,你会找到一个从Amazon美食评论数据集(CSV文件)获取向量的示例。参见获取向量

你可以使用许多向量模型,例如由Mistral AI、Cohere、Hugging Face等提供的模型。AI工具如LangChain提供了处理各种模型的接口和集成。参见LangChain: 文本向量模型。你还会在LangChain网站上找到Neon Postgres指南和Class NeonPostgres,它提供了与Neon Postgres数据库交互的接口。

在Postgres中存储向量向量

Neon支持pgvector Postgres扩展,这使得可以直接在Postgres数据库中存储和检索向量向量。在构建AI应用时,安装该扩展消除了需要扩展架构以包含单独向量存储的需求。 从Neon SQL编辑器或任何连接到你的Neon Postgres数据库的SQL客户端运行以下CREATE EXTENSION语句即可安装pgvector扩展:

CREATE EXTENSION vector;

安装 pgvector 扩展后,你可以创建一个表来存储你的向量。例如,你可以定义一个类似如下的表来存储你的向量:

CREATE TABLE items(id BIGSERIAL PRIMARY KEY, embedding VECTOR(1536));

要将向量添加到表中,你可以插入如下数据:

INSERT INTO items(embedding) VALUES ('[
    -0.006929283495992422,
    -0.005336422007530928,
    ...
    -4.547132266452536e-05,
    -0.024047505110502243
]');

有关使用pgvector的详细信息,请参阅我们的指南:pgvector扩展

查询算法

TF-IDF

TF-IDF 是一种用于评估文档中关键词重要性的方法,它通过计算关键词在文档中的频率和在整个文档集合中的逆文档频率来评估关键词的重要性。

变体:c-TF-IDF

https://maartengr.github.io/BERTopic/getting_started/ctfidf/ctfidf.html

c-TF-IDF 和传统的 TF-IDF 之间的关键区别在于它们的应用和分析层次:

传统的 TF-IDF

  • 文档级分析:TF-IDF 代表词频-逆文档频率。它是一种统计度量,用于评估单词在文档中的重要性相对于整个文档集(语料库)。
  • 计算
    • 词频(TF):测量一个术语 ( t ) 在文档 ( d ) 中出现的频率。
    • 逆文档频率(IDF):测量一个术语在所有文档中的重要性。计算公式是 ( \log \left( \frac{N}{n_t} \right) ),其中 ( N ) 是文档总数,( n_t ) 是包含术语 ( t ) 的文档数。
    • TF-IDF 得分:TF 和 IDF 的乘积。这个得分随着单词在文档中出现次数的增加而增加,但会被该单词在语料库中频率的增长所抵消。

c-TF-IDF

  • 簇/主题级分析:c-TF-IDF 将 TF-IDF 调整为在簇或类别层面上工作,而不是单个文档层面。这种方法在主题建模中特别有用,例如在 BERTopic 中。
  • 计算
    • 基于类别的词频(c-TF):每个簇(或类别)被视为单个文档。词频是基于这个合并文档中单词的频率计算的,并且针对主题大小的差异进行标准化。
    • 基于类别的逆文档频率(c-IDF):调整以考虑每个类别的平均单词数。计算公式是 ( \log \left( 1 + \frac{A}{f_x} \right) ),其中 ( A ) 是每个类别的平均单词数,( f_x ) 是单词 ( x ) 在所有类别中的频率。
    • c-TF-IDF 得分:c-TF 和 c-IDF 的乘积,给出一个单词在特定簇中的重要性相对于其他簇的得分。

c-TF-IDF 的优势

  • 更好的主题表示:通过关注文档的簇,c-TF-IDF 强调了一个簇中的文档与其他簇的文档之间的区别。
  • 定制和模块化:BERTopic 中的 c-TF-IDF 模型可以进行调优和定制,例如,应用不同的加权方案或减少频繁出现的词。
  • 增强的鲁棒性:像 bm25_weighting 和 reduce_frequent_words 这样的选项提供了对通常不会被过滤掉的常见词的额外鲁棒性。

BM25 算法

BM25 是一种基于概率的信息检索算法,用于评估文档与查询之间的相关性。BM25 算法的核心思想是通过计算文档中的关键词与查询中的关键词之间的匹配程度,来评估文档与查询之间的相关性。

BM25

Elasticsearch 默认

TF/IDF 基于相似性,具有内置的 tf 归一化,适用于短字段(如姓名)。详见 Okapi_BM25。 此相似性具有以下选项:

选项描述
k1控制非线性词频归一化(饱和)。默认值为 1.2
b控制文档长度在多大程度上归一化 tf 值。默认值为 0.75
discount_overlaps确定在计算规范时是否忽略重叠标记(位置增量为 0 的标记)。默认情况下,此值为 true,即在计算规范时不计算重叠标记。

类型名称:BM25

BM25f

介绍 Elasticsearch Relevance Engine™ — 为 AI 变革提供高级搜索能力

Jaccard 相似度

Jaccard 相似度是一种用于计算两个集合之间相似度的方法,它是通过计算两个集合的交集与并集之间的比例来评估它们之间的相似度。

Jaccard Similarity

Jaccard 相似度的计算公式如下:

J(A, B) = |A ∩ B| / |A ∪ B|

Kotlin 实现:

fun similarityScore(set1: Set<String>, set2: Set<String>): Double {
    val intersectionSize = set1.intersect(set2).size
    val unionSize = set1.union(set2).size
    return intersectionSize.toDouble() / unionSize
}

TypeScript 实现:

function similarityScore(set1: Set<string>, set2: Set<string>): number {
    const intersectionSize: number = [...set1].filter(x => set2.has(x)).length;
    const unionSize: number = new Set([...set1, ...set2]).size;
    return intersectionSize / unionSize;
}

SPLADE

SPLADE(Sequential Pattern Mining by Limited Area DEcomposition)是一种用于发现序列模式的算法,它通过将序列划分为多个子序列,并在每个子序列上应用频繁模式挖掘算法来发现序列模式。

GitHub: https://github.com/naver/splade

BM42

sentences = "Hello, World - is the starting point in most programming languages"

features = transformer.tokenize(sentences)

# ...

attentions = transformer.auto_model(**features, output_attentions=True).attentions

weights = torch.mean(attentions[-1][0,:,0], axis=0)                       
#                ▲               ▲  ▲   ▲                                 
#                │               │  │   └─── [CLS] token is the first one
#                │               │  └─────── First item of the batch         
#                │               └────────── Last transformer layer       
#                └────────────────────────── Averate all 6 attention heads

for weight, token in zip(weights, tokens):
    print(f"{token}: {weight}")

# [CLS]       : 0.434 // Filter out the [CLS] token
# hello       : 0.039
# ,           : 0.039
# world       : 0.107 // <-- The most important token
# -           : 0.033
# is          : 0.024
# the         : 0.031
# starting    : 0.054
# point       : 0.028
# in          : 0.018
# most        : 0.016
# programming : 0.060 // <-- The third most important token
# languages   : 0.062 // <-- The second most important token
# [SEP]       : 0.047 // Filter out the [SEP] token

The resulting formula for the BM42 score would look like this:

score ( D , Q ) = i = 1 N IDF ( q i ) × Attention ( CLS , q i )

向量数据存储

示例:JetBrains + Local Storage

JetBrains 在进行 IDE 搜索时支持 DiskSynchronizedEmbedding 的方式,从远程服务器下载向量向量数据,然后将其存储在本地文件系统中。 降低了对远程服务器的依赖,提高了性能和稳定性。

优势:

  • 高效的读写操作。使用RandomAccessFile进行随机访问,提供高效的读写能力,避免了将整个文件加载到内存中,提高了性能。
  • 增量更新。仅更新需要更改的部分,而不是重写整个存储文件,从而提高了写入效率,减少了资源消耗。
  • 内存使用优化。通过按需加载和写入数据,显著减少内存占用,非常适用于大规模向量向量存储场景。
  • 磁盘持久化。通过 LocalEmbeddingIndexFileManager 实现磁盘持久化存储,确保数据的持久性和可靠性。支持从磁盘加载和保存索引,增强数据恢复能力。
  • 便于管理和维护。将ID和向量向量分开存储,分别为JSON文件和二进制文件,便于管理和维护。

缺点:

  • 本地存储限制。依赖本地存储空间,可能会受到硬件限制,如果向量向量数据量非常大,可能需要频繁监控和管理存储资源。
  • 性能瓶颈。在高并发环境下,读写锁的争用可能成为性能瓶颈。极端情况下,可能会出现性能下降的问题,需要进一步优化和调整。
  • 不支持分布式访问。由于数据存储在本地文件系统中,不支持跨服务器或分布式系统访问,限制了应用场景。

示例:Sweep + Redis

Our simple vector database implementation

优势:

  • 管理多个索引的复杂性:
    • 标准的向量数据库在处理单个索引时表现良好,但在管理多个索引、频繁更新和自托管时变得复杂。
    • 使用 Redis 可以简化这一过程,无需管理多个索引和重建索引的问题。
  • 基础设施和依赖管理:
    • 使用外部存储(如 Pinecone)会引入额外的依赖和潜在的故障点。
    • Redis 是一个流行的开源内存数据库,可以轻松自托管,减少了对外部服务的依赖。
  • 缓存机制:
    • Redis 非常适合缓存用途,可以快速读取和写入数据,这对于频繁访问的 Embedding 向量非常重要。
    • 通过使用 Redis,系统可以缓存 Embedding 结果,减少对 OpenAI API 的调用次数,降低成本和延迟。

缺点:

  • 该方法速度较慢(每个查询大约1秒),但满足他们的需求。
  • 系统在超过 100 万个向量向量时扩展性不佳,但符合他们当前的需求(通常每个代码库文件少于30k)。

示例:通义灵码 + RocksDB

RocksDB 是一个开源的向量式键值存储引擎,由 Facebook 开发并开源。它在许多方面有着显著的优势:

  1. 高性能:RocksDB 被优化用于快速的随机读/写操作,适合需要高吞吐量和低延迟的应用场景。它支持并发操作,能够有效地处理大量的并发读写请求。
  2. 可调优性:RocksDB 提供了多种调优选项,允许用户根据具体的应用需求进行配置。例如,可以调整内存使用、写入策略、压缩算法等,以最大化性能和资源利用率。
  3. 持久性:RocksDB 具备持久化特性,即数据写入后可靠保存。这使得它非常适合作为后端存储引擎,支持需要持久化存储的应用程序。
  4. 可扩展性:RocksDB 的设计支持数据的水平扩展。它可以在多个节点上部署,通过分区和复制来实现数据的高可用性和可扩展性。
  5. 内存效率:RocksDB 能够有效地管理内存,尤其是对于大型数据集。它通过有效的缓存策略和紧凑的数据结构,降低了内存占用并提高了整体的效率。
  6. 灵活性:RocksDB 支持多种数据模型,包括键值对、列族存储等。这种灵活性使得它可以应用于各种不同类型的存储需求,从简单的键值存储到更复杂的列存储系统。

总体来说,RocksDB 在性能、可靠性和灵活性方面都表现出色,使其成为许多大型互联网公司和应用程序的首选存储引擎之一。

/Users/phodal/.lingma/tmp/cache/v3.3
├── 000001.vlog
├── 00001.mem
├── DISCARD
├── KEYREGISTRY
├── LOCK
└── MANIFEST

RocksDB 体积:

-rw-r--r--    1 phodal  staff    13M 13 Jul 11:04 librocksdbjni-linux-aarch64-musl.so
-rw-r--r--    1 phodal  staff    13M 13 Jul 11:02 librocksdbjni-linux-aarch64.so
-rw-r--r--    1 phodal  staff    16M 13 Jul 11:00 librocksdbjni-linux-ppc64le-musl.so
-rw-r--r--    1 phodal  staff    17M 13 Jul 11:00 librocksdbjni-linux-ppc64le.so
-rw-r--r--    1 phodal  staff    13M 13 Jul 11:09 librocksdbjni-linux-riscv64.so
-rw-r--r--    1 phodal  staff    15M 13 Jul 11:05 librocksdbjni-linux-s390x-musl.so
-rw-r--r--    1 phodal  staff    15M 13 Jul 11:05 librocksdbjni-linux-s390x.so
-rw-r--r--    1 phodal  staff    14M 13 Jul 05:39 librocksdbjni-linux32-musl.so
-rw-r--r--    1 phodal  staff    14M 13 Jul 04:49 librocksdbjni-linux32.so
-rw-r--r--    1 phodal  staff    14M 13 Jul 06:06 librocksdbjni-linux64-musl.so
-rw-r--r--    1 phodal  staff    14M 13 Jul 05:11 librocksdbjni-linux64.so
-rw-r--r--    1 phodal  staff   8.5M 13 Jul 04:28 librocksdbjni-osx-arm64.jnilib
-rw-r--r--    1 phodal  staff   9.9M 13 Jul 04:12 librocksdbjni-osx-x86_64.jnilib
-rw-r--r--    1 phodal  staff   8.0M 13 Jul 11:10 librocksdbjni-win64.dll

示例:Tabnine + Qdrant

RAG 是一种常见的人工智能框架,通过添加信息检索组件来提高LLM生成答案的准确性,该组件为模型的每个查询添加数据和上下文。 RAG 的实现包括两个组成部分:

  • 索引建立:Tabnine 构建了 RAG 索引,以便快速有效地检索相关数据。这些索引用于代码完成和聊天,可以基于本地代码或全局代码,依赖于 IDE 工作空间或组织的全局代码库中的所有代码。
  • 查询:对于 Tabnine 收到的每个用户查询(无论是显式还是隐式的),Tabnine 会从 RAG 索引中检索相关的代码上下文,并将其作为上下文添加到AI模型的提示中。结果是 Tabnine 提供了更准确的代码建议,更符合用户代码库的需求。

当涉及到 RAG 索引的内容时,可以按照以下目录进行总结:

  1. 索引类型:代码补全索引和聊天索引
  2. 索引范围:本地索引:基于每个开发者的IDE工作空间、全局索引:基于整个组织的代码库
  3. 被索引的文件类型:符合特定文件扩展名的文件、未列在 .ignore 或 .gitignore 中的文件、不包括特定扩展名的文件:"md", " yaml", "yml", "json", "lock", "xml", "gradle", "bash", "sh", "txt", "csv"
  4. 索引生命周期:本地代码补全和聊天上下文索引的创建和增量更新、连接到组织代码库的索引的定期更新
  5. 索引过程:向量向量应用于每个代码块、代码补全索引计算在开发者的本地机器上运行、聊天索引计算需要 GPU,在 Tabnine 服务器上执行
  6. 索引位置和持久化:持久化在最终用户本地机器上的向量数据库(qdrant)
  7. 与组织代码库连接的集成:与 GitHub、GitLab 或 Bitbucket 等主要 Git 托管平台的集成、保持现有权限模型,只允许用户访问其有权限的存储库

这些总结点可以帮助理解 RAG 索引的不同方面和实现方式。

示例:Neon serverless Postgres + pgvector

pgvector: 30x Faster Index Build for your Vector Embeddings

pgvector是Postgres中最受欢迎的向量相似性搜索扩展。向量搜索在语义搜索和检索增强生成(RAG)应用中变得越来越重要,增强了大型语言模型(LLMs)的长期记忆能力。

在语义搜索和RAG应用中,数据库包含LLM未训练过的知识库,被分成一系列文本或块。每个文本保存在一行,并与一个由向量模型(如OpenAI的ada-embedding-002或Mistral-AI的mistral-embed)生成的向量相关联。

向量搜索用于找到与查询向量最相似的文本。这通过将查询向量与数据库中的每一行进行比较来实现,这使得向量搜索难以扩展。因此,pgvector实现了近似最近邻(ANN)算法(或索引),通过对数据库的一个子集进行向量搜索以避免冗长的顺序扫描。

**Hierarchical Navigable Small World(HNSW)**索引是最有效的ANN算法之一。其基于图的多层结构设计用于数十亿行的向量搜索,使HNSW在大规模上极为快速和高效,因此成为向量存储市场中最受欢迎的索引之一。

HNSW的两个主要缺点

  1. 内存:HNSW索引比其他索引(如倒排文件索引IVFFlat)需要更多的内存。这个问题可以通过使用更大的数据库实例解决,但对于使用AWS RDS等独立Postgres的用户来说,可能会遇到因为索引构建而需要过度配置的问题。利用Neon的扩展能力,可以在构建HNSW索引时扩展,之后再缩减以节省成本。

  2. 构建时间:HNSW索引对于百万行数据集可能需要数小时的构建时间,这主要是由于计算向量间距离所花费的时间。pgvector 0.6.0通过引入并行索引构建解决了这一问题,使得索引构建速度提高了30倍。

并行索引构建的必要性

虽然HNSW索引支持更新,但在以下两种情况下需要重新创建HNSW索引:

  1. 希望加快查询速度并优化向量搜索时。
  2. 已有HNSW索引,但表中删除了向量时,可能会导致索引搜索返回假阳性,从而影响LLM响应质量和AI应用的整体性能。

向量模型

Massive Text Embedding Benchmark (MTEB) Leaderboard. 排名

FlagEmbedding

FlagEmbedding

BAAI/bge-small-zh-v1.5

相关库

  • FastEmbed is a lightweight, fast, Python library built for embedding generation.
  • ONNX Runtime is a cross-platform inference and training machine-learning accelerator.

ONNX Runtime 语言支持

相关资源

BERTopic

Bert Topic Modularity

示例代码:

from umap import UMAP
from hdbscan import HDBSCAN
from sentence_transformers import SentenceTransformer
from sklearn.feature_extraction.text import CountVectorizer

from bertopic import BERTopic
from bertopic.representation import KeyBERTInspired
from bertopic.vectorizers import ClassTfidfTransformer


# Step 1 - Extract embeddings
embedding_model = SentenceTransformer("all-MiniLM-L6-v2")

# Step 2 - Reduce dimensionality
umap_model = UMAP(n_neighbors=15, n_components=5, min_dist=0.0, metric='cosine')

# Step 3 - Cluster reduced embeddings
hdbscan_model = HDBSCAN(min_cluster_size=15, metric='euclidean', cluster_selection_method='eom', prediction_data=True)

# Step 4 - Tokenize topics
vectorizer_model = CountVectorizer(stop_words="english")

# Step 5 - Create topic representation
ctfidf_model = ClassTfidfTransformer()

# Step 6 - (Optional) Fine-tune topic representations with 
# a `bertopic.representation` model
representation_model = KeyBERTInspired()

# All steps together
topic_model = BERTopic(
  embedding_model=embedding_model,          # Step 1 - Extract embeddings
  umap_model=umap_model,                    # Step 2 - Reduce dimensionality
  hdbscan_model=hdbscan_model,              # Step 3 - Cluster reduced embeddings
  vectorizer_model=vectorizer_model,        # Step 4 - Tokenize topics
  ctfidf_model=ctfidf_model,                # Step 5 - Extract topic words
  representation_model=representation_model # Step 6 - (Optional) Fine-tune topic represenations
)

编码智能体:远程 AI 智能体

示例

AutoDev

详细见:https://ide.unitmesh.cc/agent/custom-ai-agent.html

[
  {
    "name": "内部 API 集成",
    "description": "在一个组织或项目中,不同系统或组件之间的通信接口。",
    "url": "http://127.0.0.1:8765/api/agent/api-market",
    "responseAction": "Direct"
  },
  {
    "name": "组件库查询",
    "description": "从组件库中检索特定的 UI 组件,以便在开发的应用程序中使用。",
    "url": "http://127.0.0.1:8765/api/agent/component-list",
    "responseAction": "TextChunk"
  },
  {
    "name": "页面生成",
    "description": "使用 React 框架,基于组件和状态来生成页面。",
    "url": "http://127.0.0.1:8765/api/agent/ux",
    "auth": {
      "type": "Bearer",
      "token": "eyJhbGci"
    },
    "responseAction": "WebView"
  },
  {
    "name": "DevInInsert",
    "description": "Update,並指定20秒的timeout時間",
    "url": "http://127.0.0.1:8765/api/agent/devins-sample",
    "responseAction": "DevIns",
    "defaultTimeout": 20
  }
]

GitHub Copilot Extension

编码智能体:测试智能体与 IDE 插件结合

示例

AutoDev

https://ide.unitmesh.cc/custom/extension-context-agent

{
    "name": "@autodev.ext-context.test",
    "description": "AutoTest",
    "url": "http://127.0.0.1:8765/api/agent/auto-test",
    "responseAction": "Direct"
}

对应的模板文件如下:

Write unit test for following ${context.lang} code.

${context.frameworkContext}

#if( $context.relatedClasses.length() > 0 )
Here is the relate code maybe you can use
${context.relatedClasses}
#end

#if( $context.currentClass.length() > 0 )
This is the class where the source code resides:
${context.currentClass}
#end
${context.extContext}
Here is the source code to be tested:

${context.imports}
${context.sourceCode}

#if($context.isNewFile)
Should include package and imports. Start method test code with Markdown code block here:
#else
Should include package and imports. Start ${context.testClassName} test code with Markdown code block here:
#end

对应的 Kotlin 代码:

private fun getCustomAgentTestContext(testPromptContext: TestCodeGenContext): String {
    if (!project.customAgentSetting.enableCustomRag) return ""

    val agent = loadTestRagConfig() ?: return ""

    val query = testPromptContext.sourceCode
    val stringFlow: Flow<String> = CustomAgentExecutor(project).execute(query, agent) ?: return ""

    val responseBuilder = StringBuilder()
    runBlocking {
        stringFlow.collect { string ->
            responseBuilder.append(string)
        }
    }

    return responseBuilder.toString()
}

编码智能体:新人上手项目

Onboarding Agent

Onboarding Agent

Onboarding Agent

Onboarding Agent 是 Tabnine Chat 中的一项新功能,专为开发人员在新项目中快速适应而设计。它通过提供关键项目信息和指导,极大地简化了开发人员的入职过程。

Onboarding Agent

  1. 集成与可用性

    • 作为 Tabnine Chat 的内置命令,无缝集成。
    • 对所有 Tabnine SaaS 用户和支持 Tabnine AI 的 IDE 兼容。
  2. 操作简便

    • 可通过简单命令 (/onboarding) 或在新对话开始时自动触发。
    • 提供项目结构、可运行脚本、依赖关系等的简明总结。
  3. 互动和个性化

    • 不仅提供信息摘要,还作为一个导游,为用户提供定制的后续问题建议。
    • 让开发人员可以根据自己的需要深入探索项目的特定部分。

对开发人员的益处:

  • 提高效率:加快了新项目的熟悉过程,节省时间。
  • 增强自主性:使开发人员能够独立地了解和操作项目。
  • 快速上手:帮助他们更快地成为项目团队的有效成员。

对组织的益处:

  • 降低成本:减少了资深团队成员辅助新人的时间成本。
  • 优化工作流程:简化了新成员加入或项目切换带来的工作中断。
  • 知识分享:促进组织内部的效率和知识共享文化。

Onboarding Agent 代表了开发工具领域的重要进展,旨在提升开发效率,加速项目启动时间,为组织带来更高的创新能力和竞争力。

编码智能体:本地 AI 智能体

JetBrains

Function Calling

The function presented serves as a comprehensive search utility within JetBrains IDEs,
It behaves like exact_search.
The only difference is that this function allows not exact queries, as search is embedding-based in this case
Use this function, IF YOU DO NOT KNOW THE **EXACT** NAME the named entity you are looking for OR if exact_search failed.",

```json
{
    "type": "object",
    "properties": {
        "searchType": {
            "type": "string",
            "enum": ["actions", "symbols", "classes", "files"]
        },
        "query": {
            "type": "string",
            "description": "Query in textual form for searching by entity names."
        }
    },
    "required": ["searchType", "query"]
}
```

exact_search:

This function serves as a robust search tool in JetBrains IDEs, allowing you to find  IDE actions (like \"save file\", \"open file\"),
symbols (functions, classes, methods), specific classes, and files containing project info like README.md. 
The search is based on the exact names of these entities, not their content, so craft your search queries accordingly.

Use this function if the exact name of what you're searching for is available, and fallback to semantic_search if unsure or unsuccessful.
In general PREFER this function over semantic_search, as the second one is more expensive. (for example if user specifies the exact class name like \"what does class <CLASS_NAME> do\")

It provides a list of search results and their IDs and could return content for short results. Avoid mentioning IDs in the response.

示例:AutoDev for VSCode

示例:Amazon Q 迁移 Agent

自定义代码库

Customizing coding companions for organizations

Indexing

Algorithms

语义检索 [Contriever, UniXcoder] 将查询和索引的代码片段转换为高维向量,并基于语义相似性对代码片段进行排序。正式来说,通常使用k近邻 (KNN) 或近似最近邻 (ANN) 搜索来找到其他具有相似语义的片段。

Semantic retrieval 过程

Amazon Q

其它相关:

编码智能体:理解 RAG 的应用

RAG 示例

RAG 过程

Advanced RAG Techniques

Indexing - textChunking

有效的索引对于任何 RAG 系统来说都至关重要。第一步涉及如何摄取、分块和存储数据。

简单文本 Chunking

  • 概述:这种方法将文档按固定大小进行分块,并带有一些重叠。这确保每个块保留前一个块的上下文。
  • 实现:可以指定一个块大小(例如 35 个字符)和一个重叠大小以在块之间保持上下文。此方法适用于简单文档,但可能不适用于更复杂的文本,也无法利用文档结构。
  • 优缺点:实现简单,但可能会打断语义单元,导致块不连贯,从而降低检索性能。

详细代码:RetrievalTutorials

特定文档 Chunking

语义化 Chunking

  • 概述:语义分块是基于意义而不是固定大小来划分文本。这种技术确保每个块代表一个连贯的信息片段。
  • 实现:计算句子嵌入之间的余弦距离。如果两个句子在语义上相似(低于某个阈值),它们属于同一个块。这种方法根据内容的语义结构创建可变长度的块。
  • 优缺点:产生更连贯和语义上有意义的块,提高检索准确性,但需要通过基于 BERT 的编码器模型进行前向传播,这比简单分块更具计算密集型。

基于图(抽象语法树)的 Chunking

  • 概述:这种方法使用抽象语法树(AST)来分块文本。AST 是代码的结构化表示,可以帮助识别代码块的边界。
  • 实现:使用 AST 解析代码,识别代码块的开始和结束。这种方法适用于代码文本,因为代码通常具有结构化的语法。
  • 优缺点:生成高质量的块,但需要专门的代码解析器,适用于代码文本,不适用于自然语言文本。

基于 LLM 的 Chunking

  • 概述:这种高级方法使用语言模型从文本中创建自包含的命题,确保每个块在语义上是完整的。
  • 实现:使用一个语言模型(例如一个拥有 70 亿参数的模型)处理文本,将其分解为独立有意义的命题。然后模型将这些命题组合成块,平衡语义完整性和上下文。这种方法计算密集,但提供最高的准确性。
  • 优缺点:适应文本细微差别,生成高质量的块,但计算密集,并且可能需要针对特定应用进行微调。

示例:https://huggingface.co/chentong00/propositionizer-wiki-flan-t5-large

基于 Agentic 的 Chunking

示例:AgenticChunker

Indexing -结合元数据

元数据提供了额外的上下文,可以显著提高检索的准确性。通过整合日期、患者年龄和既往病史等元数据,可以在搜索过程中过滤掉无关信息。过滤有助于缩小搜索范围,使检索过程更加高效和相关。

添加和基于元数据的过滤

概述:元数据提供了额外的上下文,可以显著提高检索的准确性。通过整合日期、患者年龄和既往病史等元数据,可以在搜索过程中过滤掉无关信息。过滤有助于缩小搜索范围,使检索过程更加高效和相关。

实现:在索引数据时,将元数据与矢量化文本一起存储。例如,如果索引患者记录,包含元数据如年龄、就诊日期和特定病情。在搜索时使用这些元数据过滤搜索结果,确保系统只检索相关信息。

例如,如果查询与儿科患者有关,首先过滤掉18岁以上患者的记录,然后再执行语义搜索。这减少了检索结果中的噪音,增强了输出的相关性。

MetaData Fitler

参考:MyScale

使用GLiNER为分块生成元数据

有时你可能没有丰富的元数据来增强你的分块,但使用GLiNER(通用线性命名实体识别器)模型可以实时从分块中生成元数据!GLiNER是一个基于BERT的强大模型,可以在摄取阶段对分块进行标记和标签创建元数据,从而显著改善检索过程。

自动标记与GLiNER

实现:你可以将每个分块和你想要识别的标签一起提供给GLiNER。如果在分块文本中找到这些标签,它将识别它们;如果没有匹配到高置信度的内容,则不会生成标签,从而减少误报。

优缺点:对于一般用途效果很好,但可能需要针对特定领域的数据集和应用进行微调。

查询解析和过滤

实现:GLiNER的另一个用途是解析传入的查询,并将其与标记的元数据匹配以过滤结果。

优缺点:通过确保上下文相关性提高了检索准确性,但增加了一个额外的处理步骤。

参考:GLiNER: 通用命名实体识别模型使用双向变压器。示例:GLiNER Demo

这些技术为建立一个强大的RAG系统奠定了基础,使得从大数据集中进行高效检索成为可能。选择哪种分块方法和如何使用元数据将取决于你的数据集的具体需求和特性。

Retrieval:提高矢量数据库检索召回率

为了增强RAG(Retrieval-Augmented Generation)系统中的检索部分,可以采用以下几种技术来显著提高与查询相关的文档召回率,从而提高LLM(大语言模型)生成高质量结果的几率:

1. 混合搜索

混合搜索结合了矢量搜索和关键词搜索的优势,以提高检索的准确性。

  • 矢量搜索:捕捉查询的语义含义。
  • 关键词搜索:识别特定术语的精确匹配。

在医学等领域,许多术语和概念并不是通过语义理解的,而是特定的关键词,如药物名称、解剖术语、疾病名称和诊断。纯粹的矢量搜索可能会遗漏这些关键字,而基于关键词的搜索确保了特定重要术语被考虑在内。通过整合这两种方法,混合搜索允许更全面的检索过程。

这两种搜索方法(矢量和关键词搜索)并行运行,然后根据加权系统合并和排序结果。例如,使用Weaviate,可以调整alpha参数以平衡矢量与关键词搜索结果的重要性,创建一个综合的、排序的文档列表。这种方法平衡了精度和召回率,改善了整体检索质量,但需要仔细调整加权参数。

2. 查询重写

查询重写考虑到人类查询可能并不适合矢量数据库或语言模型。通过利用语言模型重写查询,可以显著改善检索过程。

  • 矢量数据库的查询重写:将患者的初始查询转换为更适合数据库的格式。例如,将“我的左肩疼痛,拇指和食指麻木”重写为“左肩疼痛。麻木。食指麻木”。
  • 语言模型的提示重写:自动和互动式地构建提示以优化与语言模型的交互,提升生成结果的质量和准确性。框架如DSPy可以帮助实现这一过程。

这些重写的查询和提示确保检索过程更好地理解和检索相关文档,并优化语言模型的提示。可以通过以下方式实现查询重写:

示例

  • 初始查询:My left shoulder hurts and I have numbness in my thumb and index finger.
  • 重写查询:Pain left shoulder. Numbness. Numbness index finger.

这不仅使搜索过程更能理解和检索相关文档,而且使语言模型获得最佳提示,从而生成更高质量的结果。

Query Rewrite

3. 微调

Fine-Tuning Cohere's Reranker

Generation

最后,我们讨论如何提高和控制语言模型 (LLM) 的生成质量。关键在于确保提供给 LLM 的上下文尽可能与提示相关,否则不相关的数据可能会引发幻觉。以下是一些实现更好生成结果的技巧:

1. 自动剪切以移除无关信息

自动剪切是一种过滤从数据库中检索到的无关信息的方法,否则这些信息可能会误导 LLM 并导致幻觉。其工作原理如下:

  • 检索并评分相似性:当查询被提出时,会检索到多个对象及其相似性分数。
  • 识别并剪切:使用相似性分数,识别分数显著下降的截断点。超过此点的对象被认为是相关性较低的,自动排除在外。

例如,如果检索到六个对象,相似性分数可能在第四个对象后急剧下降。通过检查相似性分数的变化率,可以确定哪些对象应被排除,从而确保仅将最相关的信息提供给 LLM。

参考:AutoCut

2. 对检索到的对象重新排序

重新排序涉及使用一个更复杂的模型重新评估和重新排序初步检索到的对象,以根据其与查询的相关性增强最终检索集的质量。其工作原理如下:

  • 过度获取:初步检索到比所需数量更多的对象。
  • 应用排序模型:使用高延迟的复杂模型(通常是交叉编码器),对每个检索到的对象的相关性进行重新评估。该模型成对地考虑查询和每个检索到的对象以重新评估其相似性。
  • 重新排序结果:根据新的评估结果重新排序对象,以反映最相关的结果排在最前面。

这种方法确保最相关的文档优先,提高提供给 LLM 的数据的整体质量。

参考:AutoCut

3. 结合机器学习

PostGresML: How-to Improve Search Results with Machine Learning

以下是主要内容的总结:

  1. PostgresML的优势
    • PostgresML让在数据库中使用机器学习变得容易,并能够在云中水平扩展工作负载。
    • 通过组合不同的NLP和机器学习模型,改进搜索引擎的搜索结果。
  2. 关键字搜索
    • 搜索引擎通常由多层组成,从简单到复杂,逐步改进结果。
    • 传统的关键字搜索是基础,通过词干提取(stemming)和标准SQL函数(如to_tsvectorto_tsquery)来实现。
  3. 索引和性能优化
    • 通过生成列(generated columns)和广义倒排索引(GIN),可以显著提高搜索性能。
    • 这减少了对全表扫描的需求,使搜索更加高效。
  4. 结果排序(Ranking)
    • 排序是搜索的关键,Postgres提供了ts_rank函数,通过计算关键词匹配的词频(TF)来确定相关性分数。
    • 可以通过简单的加权公式来提升标题和正文匹配的相关性。
  5. 机器学习排序(Learning to Rank)
    • 机器学习通过用户点击数据来训练模型,从而更智能地排序搜索结果。
    • 收集用户点击数据并将其转化为特征用于训练模型,可以显著提高排序的准确性。
  6. 模型训练和预测
    • 使用pgml.train函数来训练模型,预测用户点击的概率。
    • 通过pgml.predict函数在新数据上应用训练好的模型来重新排序搜索结果。
  7. 组合查询
    • 使用公用表表达式(CTEs)和SQL的强大功能,可以分步骤高效地处理搜索和重新排序。
  8. 下一步改进
    • 添加更多特征,如文档的受欢迎度或质量指标,进一步优化预测模型。
    • 使用更复杂的机器学习算法,如XGBoost、LightGBM等,来提高排序效果。

主要步骤:

  • 创建数据表:使用标准SQL语句创建文档表,并插入样例数据。
  • 实现基础搜索:通过关键字搜索和词干提取,查找包含指定词语的文档。
  • 优化性能:生成和索引词向量,提升搜索效率。
  • 排序结果:使用ts_rank函数根据关键词匹配程度进行排序。
  • 提升相关性:通过用户点击数据训练机器学习模型,优化排序。
  • 应用模型:使用训练好的模型重新排序搜索结果。

通过以上方法,可以显著提高搜索结果的相关性和用户体验。

4. 微调 LLM

在领域特定数据上微调 LLM 可以显著增强其在该领域的表现。例如,使用类似 Meditron 70B 的模型,这是在医学数据上专门微调的 LLaMA 2 70b 版本,通过以下方式实现:

  • 无监督微调:在大量领域特定文本(如 PubMed 文献)上继续预训练模型。
  • 有监督微调:使用有监督学习在领域特定任务(如医学多项选择题)上进一步微调模型。

这种专业化的训练有助于模型在目标领域表现优异,在特定任务中超越其基础模型和更大但不专业的模型(如 GPT-3.5)。

这些技术结合在一起,确保了 LLM 生成过程中的高质量和高相关性,从而显著提升最终生成结果的可靠性和准确性。

RAG 应用开发过程

Shire RAG 示例

---
name: "Search"
variables:
  "testTemplate": /.*.java/ { caching("disk") | splitting | embedding | searching("comment") }
---

根据如下的代码,回答用户的问题:博客创建的流程

$testTemplate

代码切割

Code Splitter 模块是一个代码分割模块,用于将代码分割成多个片段,以便进行各种代码相关任务,如代码相似度计算、代码分类、代码聚类等。

拆分策略

根据《Chunking 2M+ files a day for Code Search using Syntax Trees》 的建议:

  1. 代码的平均 Token 到字符比例约为1:5(300 个 Token),而嵌入模型的 Token 上限为 512 个。
  2. 1500 个字符大约对应于 40 行,大致相当于一个小到中等大小的函数或类。
  3. 挑战在于尽可能接近 1500 个字符,同时确保分块在语义上相似且相关上下文连接在一起。

TreeSitter 语法树

结合后续更新:《Improving LlamaIndex’s Code Chunker by Cleaning Tree-Sitter CSTs

  1. Span 数据结构:引入用于高效表示字符串片段的 Span 数据结构,有助于管理和连接代码块。
  2. 处理语法树中的间隙:通过调整语法树节点的结束字节,使其与下一个节点的开始字节匹配,从而解决语法树中节点之间的间隙问题,提高了代码块的准确性。
  3. 改进的代码块化算法:使用 Span 改进了代码块化算法,使代码更清晰,更好地处理代码块的大小,确保代码块大小合适并能正确连接。
  4. 转向基于行的代码块:从字节索引转向行号,处理编码问题并消除空代码块,提升了代码块化结果的兼容性和可读性。
  5. 应对速率限制:通过分批处理文件和有选择性地重新索引活跃用户和付费用户的方法,有效管理 Modal 平台的速率限制,优化了代码库更新时的资源使用。

常规的代码分词

  • TF-IDF
  • 基于 AST
  • 基于行数

多种不同方式:

中文文档分词

分词

混合方式

Chunk/Document 拆分策略

  1. 如果代码类少于 1500 个字符,则将整个代码类作为一个代码块。
  2. 如果代码类大于 1500 个字符,则将代码类分成多个函数代码块。

代码块逻辑

  1. 代码块的第一部分是上下文相关的注释,诸如包名、类名等。
  2. 代码块的第二部分是代码块的内容。

示例:

// canonicalName: com.google.common.collect.ImmutableList

public static <T> ImmutableList<T> of(T... elements) {
    List<T> list = new ArrayList<>();
    Collections.addAll(list, elements);
    return new ImmutableList<>(list);
}

向量化(Embedding)

向量化模型

模型选择

Step-by-Step Guide to Choosing the Best Embedding Model for Your Application

Sentence Transformers

Sentence Transformers 是一个自然语言处理工具,用于将文本句子嵌入到一个高维向量空间中,以便进行各种文本相关任务,如文本相似度计算、 文本分类、聚类等。它是通过预训练的深度学习模型实现的,通常使用诸如BERT、RoBERTa、DistilBERT等预训练模型作为其基础架构。

在这里,我们使用的 SentenceTransformers 模型是:sentence-transformers/all-MiniLM-L6-v2, 在体积上只有 22M,因此被 Bloop、GitHub Copilot 作为本地向量化模型,也因此是 ChocoBuilder 的默认的本地矢量化模块。

  • all-MiniLM-L6-v2 支持转为 384 维稠密向量空间(dimensional dense vector space),即 384

可以使用 optimum 优化模型,将模型转换为 ONNX 格式,以便于在本地进行推理。

模型训练

OnnxRuntime

相关资源

距离算法

Distance Metrics in Vector Search

相似度

Netflix 相关研究:Is Cosine-Similarity of Embeddings Really About Similarity?

余弦相似度是两个向量之间夹角的余弦值,等价于它们归一化后的点积。一个常见的应用是通过将余弦相似度应用于学习得到的低维特征嵌入,来量化高维对象之间的语义相似性。在实践中,这种方法有时比未归一化的嵌入向量之间的点积效果更好,但有时也可能更差。为了深入理解这一经验观察,我们研究了基于正则化线性模型导出的嵌入,闭式解法有助于进行分析。我们从理论上推导了余弦相似度如何可能产生任意的、因此无意义的" 相似性" 。对于某些线性模型而言,这些相似性甚至不是唯一的,而对于其他模型,则受正则化的隐式控制。我们讨论了超出线性模型的影响:在学习深度模型时结合了不同的正则化技术;当对结果嵌入进行余弦相似度计算时,这些技术具有隐含的、非预期的影响,使结果变得难以理解且可能是任意的。基于这些见解,我们警告不要盲目使用余弦相似度,并概述了一些替代方法。

业内案例

混合搜索

结合:A Review of Hybrid Search in Milvus

如下提 Milvus 的混合搜索过程:

对应的 ReRanker 模块:

  • 排序检索融合(RRF)。RRF是一种数据融合算法,它基于检索结果的倒数排名进行结果的合并。它平衡了每个向量字段的影响,尤其是在没有明确的重要性优先级时。 当你希望对所有向量字段给予同等考虑,或者每个字段相对重要性不确定时,会使用这种策略。
  • 加权排名器(WeightedRanker)。加权排名器策略根据每个向量字段的重要性,为来自每个向量检索路径的结果分配不同的权重。 当每个向量字段的重要性不同时,应用这种重新排序策略,允许你通过分配更高的权重来强调某些向量字段。例如,在多模态搜索中,文本描述可能被认为比图像中的颜色分布更重要。

RAG 评估

RAG Evaluation: Detecting Hallucinations with Patronus AI and MongoDB

为什么使用 MongoDB 用于 RAG 应用程序:

  • 实时响应能力: MongoDB 的架构确保了快速的数据交互,对于生成AI系统至关重要。
  • 敏捷数据处理: 它的灵活数据模型支持快速的应用迭代,促进持续改进。
  • 智能数据集成和查询: 支持语义搜索、全文搜索、地理空间查询和向量化查询,确保高效的数据检索。
  • 安全性: 强调强大的安全控制,通过加密、基于角色的访问控制和审计功能保护敏感数据。
  • 集成性: 设计成与任何云提供商、LLM和框架无缝集成,支持生成AI应用程序的动态需求。

框架: Verba

Verba 金毛寻回犬(Golden RAGtriever),是一款开源应用程序。它旨在为用户提供开箱即用的端到端、简化和用户友好的界面,用于检索增强生成(Retrieval-Augmented Generation,简称RAG)。用户只需简单几步,即可轻松探索数据集并提取洞见。无论是本地使用HuggingFace和Ollama,还是通过OpenAI、Cohere和Google等大型语言模型(LLM)提供商,操作都十分便捷。

Verba Architeture

编码任务 Agent

示例

CodexGraph

CodexGraph

大型语言模型(LLMs)在独立的代码任务(如HumanEval和MBPP)方面表现出色,但在处理整个代码库方面存在困难。这个挑战促使研究人员在代码库规模上增强 LLM-代码库交互的研究。目前的解决方案依赖于基于相似性的检索或手动工具和API,每种方法都有明显的缺点。基于相似性的检索在复杂任务中通常具有低召回率, 而手动工具和API通常是特定于任务的,需要专业知识,降低了它们在不同代码任务和实际应用中的通用性。为了缓解这些限制,我们介绍了\framework, 这是一个将LLM代理与从代码库中提取的图数据库接口集成的系统。通过利用图数据库的结构属性和图查询语言的灵活性,\framework使LLM代理能够构建和执行查询, 从而实现精确的、代码结构感知的上下文检索和代码导航。我们使用三个基准测试评估了\framework:CrossCodeEval、SWE-bench和EvoCodeBench。 此外,我们开发了五个真实的编码应用程序。通过一个统一的图数据库模式,\framework在学术和实际环境中展示了竞争性能和潜力,展示了它在软件工程中的多样性和功效。

我们的应用演示:https://github.com/modelscope/modelscope-agent/tree/master/apps/codexgraph_agent。

编码智能体:Copilot Chat 是如何工作的

1. Deciding which workspace information to collect
2. Determining workspace structure…
3. Asking the model to update the user question and provide queries…
4. Running all tools…
5. Collecting workspace information

RAG 过程

Workspace Agent 模型策略

2024-04-15 11:46:05.940 [info] [chat fetch] url https://api.githubcopilot.com/chat/completions
2024-04-15 11:46:05.940 [info] [chat fetch] modelMaxPromptTokens 3072
2024-04-15 11:46:05.940 [info] [chat fetch] modelMaxResponseTokens 4096
2024-04-15 11:46:05.940 [info] [chat fetch] chat model gpt-4
2024-04-15 11:46:07.735 [info] [chat fetch] request.response: [https://api.githubcopilot.com/chat/completions], took 1795 ms
2024-04-15 11:46:19.135 [info] [streamMessages] message 0 returned. finish reason: [stop]
2024-04-15 11:46:19.136 [info] [streamChoices] request done: requestId: [d81668fd-e22d-4cd0-b899-e4a054efb7d3] responseId: [d81668fd-e22d-4cd0-b899-e4a054efb7d3] model deployment ID: []
2024-04-15 11:46:19.153 [info] [chat fetch] url https://api.githubcopilot.com/chat/completions
2024-04-15 11:46:19.153 [info] [chat fetch] modelMaxPromptTokens 7168
2024-04-15 11:46:19.153 [info] [chat fetch] modelMaxResponseTokens 4096
2024-04-15 11:46:19.153 [info] [chat fetch] chat model gpt-3.5-turbo
2024-04-15 11:46:19.785 [info] [chat fetch] request.response: [https://api.githubcopilot.com/chat/completions], took 631 ms
2024-04-15 11:46:19.785 [info] [streamMessages] message 0 returned. finish reason: [stop]
2024-04-15 11:46:19.786 [info] [streamChoices] request done: requestId: [f7263ca2-0fa3-47d6-bb15-4929896db8fa] responseId: [f7263ca2-0fa3-47d6-bb15-4929896db8fa] model deployment ID: [x4dff5e5d11fc]

理解阶段:GPT 4 生成本地查询机制数据

{
 rephrasedQuestion: "Where's the code for base64 encoding?",
 keywords: [
   {
     keyword: "base64 encoding",
     variations: ["base64 encoder", "base64 encode"]
   },
   {
     keyword: "base64",
     variations: ["base 64"]
   },
   {
     keyword: "encode",
     variations: ["encoded", "encoder", "encoders"]
   }
 ]
}

总结阶段:GPT 3.5 Turbo 根据返回生成

生成数据示例:

IDE 信息准备

{ header: 'Relevant function implementations', findImpls: relevantFunction },
{ header: 'Relevant class declarations', findImpls: relevantClass },
{ header: 'Relevant type declarations', findImpls: relevantType }
[
 (constructor_declaration
  name: (identifier) @identifier
  body: (constructor_body) @body)
 (method_declaration
  name: (_) @identifier
  body: (block) @body)
 (lambda_expression
  body: (block) @body)
] @function

编码智能体:代码问答 Agent 示例

问答策略

全局 vs. 局部上下文

远程 vs. 本地相关上下文

业务导向还是技术逻辑导向

示例

Sweep:issue-to-pull-request 功能

相关文章:Sweep's Core Algorithm - Using Retrieval Augmented Generation (RAG) to clear your GitHub Backlog

Sweep

Sweep 的核心算法可以总结为以下四个主要阶段:

  1. 搜索

    • 目的:检索相关的代码片段和上下文。
    • 过程 :根据问题描述查询代码库,获取顶级代码片段。使用 MPNet 向量化和 DeepLake 向量存储。
    • 步骤
      • 根据问题上下文搜索代码片段。
      • 重排。基于提交计数和最新提交时间的启发式方法对片段进行重新排序
      • 去重和合并代码片段。
      • 使用 ctag 总结生成仓库摘要
  2. 规划

    • 目的:确定修改和新创建的文件。
    • 过程:分析问题的根本原因并规划变更。
    • 步骤
      • 使用自然语言规划实现方案。
      • 指定要修改或创建的文件。
      • 根据需要验证和调整修改方案。
  3. 执行

    • 目的:在代码库中实施规划的变更。
    • 过程
      • 创建新文件或修改现有文件。
      • 辨识并描述具体变更及其涉及的行号。
      • 使用搜索和替换对进行修改。
      • 对于大文件使用流式方法处理。
  4. 验证

    • 目的:确保实施变更的正确性。
    • 过程
      • 使用基于LLM和程序的验证检查代码错误和功能。
      • 进行自我审查,必要时进行迭代。
      • 利用GitHub Actions进行额外的验证。

从搜索代码片段到验证变更的每个阶段都确保了一种系统化的方法,通过自动化流程和GPT-4驱动的类人推理来进行代码修改和创建。

Sweep 开始搜索相关代码片段的步骤如下:

  1. 使用 MPNet 嵌入和 DeepLake 向量存储,通过标题和描述在代码片段上下文中查询,并检索前 100 个片段。我们提前使用基于 CST 的自定义分块器对文件进行分块。更多关于我们的搜索基础设施的详细介绍请参见 https://docs.sweep.dev/blogs/search-infrahttps://docs.sweep.dev/blogs/building-code-search
  2. 使用基于提交次数和最新提交时间的启发式方法重新排序片段,并选取前 4 个。假设最新提交且提交次数最多的文件更有可能再次被编辑。在这一点上,我们还会添加任何直接提到的文件。
  3. 对片段进行去重和融合。例如,如果获取到的片段是 main.py:0-50 和 main.py:51-100,则它们会被融合为 main.py:0-100。然后我们在每个方向上扩展每个片段 25 行,因此 main.py:25-75 变为 main.py:0-100。
  4. 使用 ctag 摘要生成仓库的摘要。摘要包含重新排序后前 10 个文件的变量名和函数声明。这以目录树的形式呈现:从根目录开始一直到文件以及文件中的类、方法和变量。只有前 10 个文件的同级文件会被包含在内。

此时的最终上下文大致如下:

<relevant_snippets>
<snippet file_path="main.py" start_line="1" end_line="56">
import numpy as np
...
</snippet>
<snippet file_path="test.py" start_line="1" end_line="32">
import pytest
...
</snippet>
...
</relevant_snippets>
 
<repo_tree>
.gitignore
jp-app/
|- App.xaml
|- App.xaml.cs
|   |- namespace jp_app
|   |- class App
|   |- method App (ISystemLanguageService systemLanguageService)
|   |- method OnStart ()
</repo_tree>
 
Repo name: sweepai/sweep: an AI junior dev
Username: kevinlu1248
Query: Sweep: Use os agnostic temp directory for windows

Cody

How Cody understands your codebase

如何在提示中使用上下文

当用户通过聊天消息或命令向 Cody 查询时,Cody 首先会编译一个 prompt。Cody 将用户的输入整理成一个提示词,以便从大型语言模型(LLM)中获取最佳响应。 提示分为三部分:

  1. 前缀(Prefix)。描述所需输出的可选说明。Cody经常使用前缀,例如,当开发人员触发一个命令时,这个命令是预定义的任务,旨在返回特定的输出格式。例如,对于"Test"命令,Cody会使用前缀来定义输出格式为单元测试。
  2. 用户输入(User input)。用户提供的查询。
  3. 上下文(Context)。Cody查找并检索的附加信息,以帮助LLM提供相关答案。

Prompt Construction

示例说明

例如,当用户触发 Cody 的 "Explain" 命令时,Cody生成的提示可能如下所示:

  • 前缀

    Explain the following Go code at a high level. Only include details that are essential to an overall understanding of what's happening in the code.
    
  • 用户输入

    zoekt.QueryToZoektQuery(b.query, b.resultTypes, b.features, typ)
    
  • 上下文

    [Contents of sourcegraph/sourcegraph/internal/search/zoekt/query.go]
    

这个完整的提示,包括所有三部分内容,然后被发送到 LLM。LLM 根据提示中包含的信息以及其基线模型中的信息进行工作。任何有关用户代码库的问题, 只有在上下文(作为提示的一部分发送)提供了足够的信息时,LLM 才能回答。

SourceGraph Cody 示例

Sourcegraph Cloud

问答示例

  1. 广泛的上下文检索:对于聊天和命令,Cody 需要覆盖用户可能询问的整个代码库的广泛上下文。
  2. Sourcegraph 代码智能平台:Cody 利用 Sourcegraph 的平台,该平台可以索引并理解来自多个存储库(从几个到超过10万个)的代码。
  3. 搜索和上下文选择
    • 用户查询处理:当用户调用 Cody 时,可以选择最多10个存储库。Cody会预处理用户查询,将其标记化并去除多余的信息。
    • 搜索引擎:然后,这些标记由 Sourcegraph 的搜索引擎处理,扫描选定的存储库。
    • 相关性排名:Cody 使用改进的 BM25 排名函数和其他调整过的信号,根据搜索查询的相关性对文件片段进行排名。最相关的片段会被发送回Cody。
  4. 本地上下文整合:Cody 还会整合用户 IDE 中打开文件的本地上下文,将这些与从 Sourcegraph 搜索中检索到的片段结合起来。
  5. 全局排名和提示构建:Cody 对所有片段进行全局排名,并根据长度选择最相关的片段来构建提示的上下文。这个上下文连同用户输入一起被发送到LLM(大语言模型)以生成响应。

例如,用户可能会询问:How it auto generate test for Java?

Retrieval-based QA:


Searched entire codebase for relevant files

java/src/test/kotlin/cc/unitmesh/idea/java/JavaAutoProcessorTest.kt
java/src/test/kotlin/cc/unitmesh/idea/java/JavaCodeProcessorTest.kt
java/src/test/kotlin/cc/unitmesh/idea/java/JavaSpringCodeCreatorTest.kt
java/src/test/kotlin/cc/unitmesh/idea/java/JavaParseUtilTest.kt
java/src/test/kotlin/cc/unitmesh/idea/provider/JvmAutoDevFlowTest.kt
src/main/resources/intentionDescriptions/DefaultDocumentationIntention/description.html
java/src/test/kotlin/cc/unitmesh/idea/provider/JvmPromptStrategyTest.kt
java/src/test/kotlin/cc/unitmesh/idea/java/SpringLayerCharacteristicTest.kt
java/src/main/kotlin/cc/unitmesh/idea/provider/JavaTestDataBuilder.kt
java/src/main/kotlin/cc/unitmesh/idea/context/JavaCodeModifier.kt
webstorm/src/main/kotlin/cc/unitmesh/ide/webstorm/provider/testing/JavaScriptTestCodeModifier.kt
java/src/test/kotlin/cc/unitmesh/idea/context/JavaContextCollectionUtilsKtTest.kt
docs/features/auto-dev.md
README.md
docs/index.md

Here are some ways AutoDev can auto generate tests for Java code:

  • When you create a new Java class or method, AutoDev provides an intention action to generate a test stub. This creates a skeleton test class and methods in the test folder.
  • When you make changes to existing code, AutoDev analyzes the changes and suggests relevant tests to add or update via intention actions. For example, adding a new method would suggest creating a test method.
  • AutoDev can generate test data models based on method parameters and return types. It analyzes the code structures and provides sample test data.
  • For common architectures like Spring MVC, AutoDev has predefined templates to generate component tests for layers like Controllers, Services etc.
  • AutoDev integrates with test runners like JUnit. It can auto-run tests and if there are failures, provide quick fixes and suggestions to update tests.
  • The test generation works both for unit tests and integration tests. AutoDev looks at package names, configs and contexts to determine which type of tests to create.

In summary, AutoDev aims to reduce manual test writing by auto generating skeletons and suggestions, analyzing contexts and architectures, and integrating with testing workflows. Let me know if you have any other questions!

中文:AutoDev 是如何实现自动生成 Java 测试代码的?

Searched entire codebase for relevant files

java/src/test/kotlin/cc/unitmesh/idea/provider/JvmAutoDevFlowTest.kt
src/main/resources/prompts/openai/update_service_method.vm
src/main/resources/intentionDescriptions/AutoDevIntentionHelper/description.html
src/main/resources/intentionDescriptions/AutoDevIntention/description.html
src/main/resources/prompts/openai/create_service_and_repository.vm
plugin/description.html
src/main/resources/intentionDescriptions/DefaultDocumentationIntention/description.html
java/src/test/kotlin/cc/unitmesh/idea/java/JavaCodeProcessorTest.kt
java/src/test/kotlin/cc/unitmesh/idea/java/JavaParseUtilTest.kt
java/src/test/kotlin/cc/unitmesh/idea/java/JavaAutoProcessorTest.kt
java/src/main/kotlin/cc/unitmesh/idea/flow/JvmAutoDevFlow.kt
src/main/resources/prompts/openai/create_controller.vm
README.md
docs/features/auto-dev.md
docs/index.md

根据 AutoDev 的代码,它实现自动生成 Java 测试代码的主要方式是:

  1. 提供一个创建测试的 Intention 动作。当在 Java 代码中调用这个 Intention 时,会触发自动生成测试代码的逻辑。
  2. 在后台使用 OpenAI Codex 模型自动生成测试代码。主要流程是:
    • 收集当前需要测试的 Java 代码作为 Prompt。
    • 向 OpenAI 提交生成测试代码的请求。
    • 获取 OpenAI 返回的测试代码。
    • 处理测试代码,插入到项目中合适的测试类或测试方法中。
  3. 生成的测试代码会包含基本的单元测试框架代码,以及针对主代码的一些典型测试用例。
  4. 生成后的测试代码还会尝试自动运行,如果测试失败,会再次请求 OpenAI 生成修复测试代码的建议。

所以整体上,AutoDev 主要通过 UI 操作触发,配合 OpenAI 自动生成代码的能力,来实现自动化测试代码的生成。

问答数据流

Cody Chat Dataflow

Cody在两种场景下的上下文构建方式不同,分别是聊天/命令和自动完成。

聊天和命令
  1. 广泛的上下文检索:对于聊天和命令,Cody 需要覆盖用户可能询问的整个代码库的广泛上下文。
  2. Sourcegraph 代码智能平台:Cody 利用 Sourcegraph 的平台,该平台可以索引并理解来自多个存储库(从几个到超过10万个)的代码。
  3. 搜索和上下文选择
    • 用户查询处理:当用户调用 Cody 时,可以选择最多10个存储库。Cody会预处理用户查询,将其标记化并去除多余的信息。
    • 搜索引擎:然后,这些标记由 Sourcegraph 的搜索引擎处理,扫描选定的存储库。
    • 相关性排名:Cody 使用改进的 BM25 排名函数和其他调整过的信号,根据搜索查询的相关性对文件片段进行排名。最相关的片段会被发送回Cody。
  4. 本地上下文整合:Cody 还会整合用户 IDE 中打开文件的本地上下文,将这些与从 Sourcegraph 搜索中检索到的片段结合起来。
  5. 全局排名和提示构建:Cody 对所有片段进行全局排名,并根据长度选择最相关的片段来构建提示的上下文。这个上下文连同用户输入一起被发送到LLM(大语言模型)以生成响应。
自动补全

自动补全:

  1. 速度和本地上下文优先:自动补全需要非常快,优先考虑本地上下文而不是远程搜索。
  2. 意图解析:使用Tree-Sitter,Cody 解析用户的输入以确定最相关的完成体验,无论是填充函数体、编写文档字符串还是实现方法调用。
  3. 本地上下文检索:Cody 从各种本地来源(如活动文件、其他打开的标签页和最近关闭的标签页)检索上下文。
  4. 上下文打包和补全:它识别相关的代码段,将最相关的片段打包成一个提示。这提示被发送到一个针对完成任务优化的 LLM,生成的建议会作为虚拟文本显示在用户光标前。
Embeddings 转变

Cody最初使用 Embeddings(高维数据的密集向量表示)来检索上下文,但由于几个缺点而放弃了:

  • 数据隐私:将代码发送到 OpenAI 进行处理存在隐私问题。
  • 维护复杂性:创建和更新嵌入增加了 Sourcegraph 管理员的复杂性。
  • 可扩展性:处理大型代码库(超过10万个存储库)的嵌入非常耗费资源,限制了多存储库上下文功能的构建。

新系统利用 Sourcegraph 的本地平台,避免了这些问题,因为不需要外部处理,也不需要额外配置,并且可以更有效地扩展。然而,Embeddings 可能在未来改进中继续探索。

Aider - 仓库映射提供上下文

aider 的最新版本会随每个修改请求向 GPT 发送一个仓库映射。这个映射包含仓库中所有文件的列表,以及每个文件中定义的符号。像函数和方法这样的可调用对象还包括它们的签名。

  • GPT 可以看到仓库中所有地方的变量、类、方法和函数签名。仅此一项可能已经为其提供了足够多的上下文来解决许多任务。例如,它可能可以仅基于映射中显示的细节来理解如何使用模块导出的 API。
  • 如果需要查看更多代码,GPT 可以使用映射自行确定需要查看的文件。然后,GPT 将要求查看这些特定文件,而 aider 将自动将它们添加到对话上下文中(经过用户批准)。

当然,对于大型代码库,即使仅仅映射可能也太大了以至于超出上下文窗口的能力。然而,这种映射方法扩展了与 GPT-4 在比以往更大的代码库上合作的能力。它还减少了手动选择要添加到对话上下文中的文件的需要,使 GPT 能够自主识别与当前任务相关的文件。

从 Ctags 到 TreeSitter

Improving GPT-4’s codebase understanding with ctags

tree-sitter 仓库映射取代了 aider 最初使用的基于 ctags 的映射。从 ctags 切换到 tree-sitter 带来了许多好处:

  • 映射更丰富,直接显示源文件中的完整函数调用签名和其他详细信息。
  • 借助 py-tree-sitter-languages,我们通过一个 python 包获得了对许多编程语言的全面支持,该包在正常的 pip 安装 aider-chat 的过程中自动安装。
  • 我们消除了用户通过某些外部工具或软件包管理器(如 brew、apt、choco 等)手动安装 universal-ctags 的要求。
  • Tree-sitter 集成是实现 aider 未来工作和能力的关键基础。

一些可能减少映射数据量的方法包括:

  • 精简全局映射,优先考虑重要符号并丢弃"内部"或其他全局不相关的标识符。可能可以借助 gpt-3.5-turbo 在灵活且与语言无关的方式中进行这种精简。
  • 提供机制让 GPT 从精简的全局映射子集开始,并允许它要求查看其感觉与当前编码任务相关的子树或关键词的更多细节。
  • 尝试分析用户给出的自然语言编码任务,并预测什么样的仓库映射子集是相关的。在特定的仓库内进行先前编码对话的分析可能有助于此工作。针对 chat history、仓库映射或代码库的向量和关键字搜索可能有所帮助。

一个关键目标是优先选择语言无关或可以轻松部署到大多数流行编程语言的解决方案。ctags 解决方案具有这种优势,因为它预先支持大多数流行语言。我怀疑语言服务器协议可能比 ctags 更适合这个问题。但是,对于广泛的语言,它的部署可能更为繁琐。用户可能需要为他们感兴趣的特定语言搭建一个 LSP 服务器。

Tabbml

Repository context for LLM assisted code completion

以下是提供的文本的中文总结:

使用语言模型(LLMs)进行编码任务:

  • 优势:在独立编码任务中,如创建新的独立函数时,基于编码数据预训练的LLMs表现出色。
  • 挑战:当应用于复杂的现有代码库时,LLMs由于依赖关系和链接子系统的API而面临挑战。

应对上下文挑战:

  • 需要上下文:LLMs需要代码库的上下文来理解依赖关系,并生成与现有抽象相集成的代码。
  • 最佳上下文传输:由于大小限制和推理速度的限制,每个请求中发送整个代码库是不切实际的。
  • 选择性上下文化:选择性地发送相关片段(如特定函数定义)优化了提供给LLMs的上下文,避免了超载上下文窗口。

高效的上下文处理:

  • 手动与自动上下文选择:手动选择片段不理想;利用Tree-sitter进行索引创建和检索的自动化方法提高了效率。
  • Tree-sitter集成:利用Tree-sitter解析和索引代码,有效提取LLMs上下文所需的相关片段。
  • 片段格式:片段格式化保持代码语义,有助于LLMs理解而不干扰现有代码。

未来发展:

  • 增强检索和排名:持续改进片段索引和检索算法(如注意力权重热图),旨在优化LLMs在编码任务中的效果。
  • 迭代开发:持续改进以增强LLMs在复杂代码库中提供上下文的质量和效率。

结论:

该方法强调了上下文在提升LLMs在编码任务中性能方面的关键作用,平衡了全面理解的需求与上下文窗口大小和推理速度的实际限制。通过选择性提供上下文片段和利用Tree-sitter等先进解析技术,该方法旨在在复杂代码库中最大化LLMs的效用,同时最小化计算开销。

Continue

https://github.com/continuedev/continue

https://docs.continue.dev/features/codebase-embeddings

Continue 会为你的代码库建立索引,以便稍后能够自动从整个工作区中提取最相关的上下文。这是通过嵌入检索和关键词搜索的组合实现的。默认情况下,所有嵌入都是在本地使用 all-MiniLM-L6-v2 计算,并存储在本地的 ~/.continue/index 中。

目前,代码库检索功能以“codebase”和“folder”上下文提供者的形式提供。你可以通过在输入框中输入 @codebase 或 @folder 来使用它们,然后提问。输入框的内容会与代码库(或文件夹)的嵌入进行比较,以确定相关文件。

以下是一些常见的用例:

  • 针对你的代码库提出高级问题

    • “如何向服务器添加新端点?”
    • “我们是否在任何地方使用了 VS Code 的 CodeLens 功能?”
    • “是否已有将 HTML 转换为 markdown 的代码?”
  • 使用现有示例生成代码

    • “生成一个带有日期选择器的新 React 组件,使用现有组件的相同模式”
    • “使用 Python 的 argparse 为这个项目编写一个 CLI 应用程序的初稿”
    • “在 bar 类中实现 foo 方法,遵循其他 baz 子类中的模式”
  • 使用 @folder 针对特定文件夹提问,提高获得相关结果的可能性

    • “这个文件夹的主要用途是什么?”
    • “我们如何使用 VS Code 的 CodeLens API?”
    • 或者使用 @folder 代替 @codebase 提出上述问题

以下是一些不适用的场景:

  • 当你需要 LLM 查看代码库中的每个文件时

    • “查找 foo 函数被调用的所有地方”
    • “检查我们的代码库,找出任何拼写错误”
  • 重构代码

    • “为 bar 函数添加一个新参数,并更新所有调用处”

Bloop

https://github.com/BloopAI/bloop

bloop 是为你的代码提供支持的 ChatGPT。你可以使用自然语言提问,搜索代码,并基于现有代码库生成补丁。

工程师们通过使用 bloop 提高工作效率,包括:

  • 用简单的语言解释文件或功能的工作原理
  • 基于现有代码编写新功能
  • 理解文档不完善的开源库的使用方法
  • 精确定位错误
  • 使用其他语言提问关于英文代码库的问题
  • 通过检查现有功能减少代码重复

功能特点

  • 基于 AI 的对话式搜索
  • Code Studio,一个使用你代码作为上下文的 LLM(大语言模型)游乐场
  • 超快速的正则表达式搜索
  • 同步本地和 GitHub 仓库
  • 高级查询过滤器,可以缩小搜索结果范围
  • 使用符号搜索查找函数、变量或特性
  • 精确的代码导航(跳转到引用和定义),支持 10 多种最流行的语言,基于 Tree-sitter 构建
  • 注重隐私的设备端嵌入,用于语义搜索

其它相关论文

CodePlan: Repository-level Coding using LLMs and Planning

软件工程活动,如软件包迁移、修复静态分析或测试中的错误报告,以及向代码库添加类型注解或其他规范,涉及广泛编辑整个代码库。 我们将这些活动称为代码库级别的编码任务。像 GitHub Copilot 这样的最近工具,由大型语言模型(LLMs)驱动,已成功地为局部编码问题提供了高质量的解决方案。代码库级别的编码任务更为复杂,不能直接使用 LLMs 解决,因为代码库内部相互依赖,并且整个代码库可能太大而无法适应输入。我们将代码库级别的编码视为一个规划问题,并提出了一个与任务无关的神经 符号框架CodePlan来解决它。CodePlan 综合了多步骤的编辑链(计划),其中每一步都会调用LLM处理来自整个代码库、先前代码更改和任务特定指令的上下文信息。

CodePlan 基于增量依赖分析、变更影响分析和自适应规划算法(符号组件)与神经 LLMs 的创新结合。我们评估了 CodePlan 在两个代码库级别任务上的有效性: 软件包迁移(C#)和时间相关的代码编辑(Python)。每个任务在多个代码库上进行评估, 每个代码库都需要对许多文件进行相互依赖的更改(2 至 97 个文件之间)。 以往没有使用 LLMs 自动化处理这种复杂程度的编码任务。我们的结果显示,与基准相比,CodePlan 与实际情况更匹配。CodePlan 能够使 5/7 个代码库通过有效性检查(即无错误地构建并进行正确的代码编辑),而基准(没有规划但具有与 CodePlan 相同类型的上下文信息)则无法使任何一个代码库通过检查 。

我们在https://github.com/microsoft/codeplan 提供了我们的(非专有)数据、评估脚本和补充材料。

编码智能体分析:Copilot Workspace

示例

使用Copilot Workspace的实现步骤

Copilot Workspace: What It Is, How It Works, Why It Matters

以下是如何利用 Copilot Workspace 来实现该功能的方法:

  1. 任务创建:首先创建一个GitHub issue,任务是将应用程序改为多语言版本。具体任务是将(BGE-M3)多语言模型集成到现有的RAG系统中。
  2. 规范:Copilot Workspace分析任务并生成高级规范,确定需要更新数据处理管道以处理多种语言,并修改RAG系统以利用BGE-M3提供多语言支持。
  3. 规划:Workspace接着生成详细的计划。包括以下步骤:
    • 更新数据摄取过程以包含多语言数据。
    • 修改现有的Milvus设置以支持BGE-M3。
    • 调整RAG系统以利用BGE-M3的多语言功能。
    • 测试系统以确保其能够支持多种语言。
  4. 编码:基于验证后的计划,Copilot Workspace生成必要的代码:
    • 更新数据摄取脚本以预处理和索引多语言数据到Milvus中。
    • 配置Milvus代码以使用BGE-M3嵌入进行多语言的相似性搜索。
    • 修改RAG系统以使用多语言模型查询Milvus并检索相关结果。
  5. 审查和测试:审查生成的代码,进行必要的调整并测试更改。
  6. 拉取请求和合并:满意后,打开一个拉取请求与团队审查更改。最终验证后,合并更改,使应用程序支持多语言功能。

编码智能体:RAG 数据与 AI 安全

在当今的数字化时代,数据安全和隐私保护已成为科技发展的重中之重。随着人工智能技术的飞速发展,如何确保数据在智能体处理过程中的安全性,成为了一个亟待解决的问题。 本文将探讨编码智能体在处理RAG(检索增强生成)数据时,如何保障AI安全,并通过几个具体案例来阐述。

经验示例

示例 1:GitHub Secret

在GitHub中,开发者有时会不小心将敏感信息如API密钥等提交到代码仓库中。以下是一个示例,展示了GitHub如何检测并阻止包含敏感信息的push操作:

Current branch main is up to date.
Enumerating objects: 32, done.
Counting objects: 100% (32/32), done.
Delta compression using up to 16 threads
Compressing objects: 100% (16/16), done.
Writing objects: 100% (19/19), 4.59 KiB | 1.15 MiB/s, done.
Total 19 (delta 10), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (10/10), completed with 7 local objects.
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: 
remote: - GITHUB PUSH PROTECTION
remote:   —————————————————————————————————————————
remote:     Resolve the following violations before pushing again
remote: 
remote:     - Push cannot contain secrets
remote: 
remote:     
remote:      (?) Learn how to resolve a blocked push
remote:      https://docs.github.com/code-security/secret-scanning/pushing-a-branch-blocked-by-push-protection
remote:     
remote:     
remote:       —— OpenAI API Key ————————————————————————————————————
remote:        locations:
remote:          - commit: 620252f31718c63dbc6c89d0c0b989187489ef1c
remote:            path: docs/guarding/pipeline-guarding.md:34
remote:          - commit: bb7952d77a7c76a4d29c97bb049af3e709d543f0
remote:            path: docs/guarding/pipeline-guarding.md:34
remote:          - commit: bb7952d77a7c76a4d29c97bb049af3e709d543f0
remote:            path: shirelang/src/test/kotlin/com/phodal/shirelang/ShirePatternPipelineTest.kt:116
remote:     
remote:        (?) To push, remove secret from commit(s) or follow this URL to allow the secret.
remote:        https://github.com/phodal/shire/security/secret-scanning/unblock-secret/xxx
remote:     
remote: 
remote: 

此示例显示了GitHub的push保护机制如何检测到代码中包含的OpenAI API密钥,并阻止了push操作,同时提供了如何解决这一问题的指南。

示例

Unkey Semantic Cache

在处理自然语言查询时,一个简单的缓存策略是将用户的查询作为键,将工作流的结果作为值。但这种方法有一个缺点,即它依赖于用户查询的表述完全相同。 为了解决这个问题,语义缓存应运而生。以下两张图表展示了缓存命中和缓存未命中的情况:

unkey-cachehit.webp unkey-cachemiss.webp

通过基于查询嵌入的缓存,语义缓存确保即使查询的表述不同,只要意图相同,用户就能命中缓存。

Microsoft Presidio

Presidio是一个由Microsoft开发的工具,旨在帮助组织快速识别和匿名化敏感数据。它能够处理文本和图像中的各种敏感信息,如信用卡号码、姓名、位置等。

presidio-analyze-anonymize.png presidio-ner-flow.png

Presidio分析器是一个基于Python的服务,用于检测文本中的PII(个人身份信息)实体。它运行一组不同的PII识别器,每个识别器负责使用不同的机制检测一个或多个PII实体。

SkyFlow

https://www.skyflow.com/product/llm-privacy-vault

Protect AI LLM Guard

Supported scanners

Prompt scanners

  • Anonymize,acts as your digital guardian, ensuring your user prompts remain confidential and free from sensitive data exposure.
  • BanCode,is designed to detect and ban code in the prompt.
  • BanCompetitors, scanner is designed to prevent the inclusion of competitor names in the prompts submitted by users. This scanner ensures that prompts containing references to known competitors are either flagged or altered, according to user settings, to maintain a strict focus on the user's own products or services.
  • BanSubstrings, Ensure that specific undesired substrings never make it into your prompts with the BanSubstrings scanner.
  • BanTopics, designed to restrict specific topics, such as religion, violence, from being introduced in the prompt using Zero-Shot classifier.
  • Code, is designed to detect and validate code in the prompt.It can be particularly useful in applications that need to accept only code snippets in specific languages.
  • Gibberish, is designed to identify and filter out gibberish or nonsensical inputs in English language text. It proves invaluable in applications that require coherent and meaningful user inputs, such as chatbots and automated processing systems.
  • InvisibleText, is designed to detect and remove non-printable, invisible Unicode characters from text inputs. This is crucial for maintaining text integrity in Large Language Models (LLMs) and safeguarding against steganography-based attacks.
  • Language, identifies and assesses the authenticity of the language used in prompts.
  • PromptInjection, specifically tailored to guard against crafty input manipulations targeting large language models ( LLM). By identifying and mitigating such attempts, it ensures the LLM operates securely without succumbing to injection attacks.
  • Regex, is designed to sanitize prompts based on predefined regular expression patterns. It offers flexibility in defining patterns to identify and process desirable or undesirable content within the prompts.
  • Secrets, diligently examines user inputs, ensuring that they don't carry any secrets before they are processed by the language model.
  • Sentiment, scans and evaluates the overall sentiment of prompts using the SentimentIntensityAnalyzer from the NLTK ( Natural Language Toolkit) library.
  • TokenLimit, ensures that prompts do not exceed a predetermined token count, helping prevent resource-intensive operations and potential denial of service attacks on large language models (LLMs).
  • Toxicity, provides a mechanism to analyze and mitigate the toxicity of text content, playing a crucial role in maintaining the health and safety of online interactions. This tool is instrumental in preventing the dissemination of harmful or offensive content.

Output scanners

  • BanCompetitors, is designed to identify and handle mentions of competitors in text generated by Large Language Models (LLMs). This scanner is essential for businesses and individuals who wish to avoid inadvertently promoting or acknowledging competitors in their automated content.
  • BanSubstrings, scanner provides a safeguard mechanism to prevent undesired substrings from appearing in the language model's outputs.
  • BanTopics, is designed to detect outputs that touch upon topics that are considered sensitive using Zero-Shot classifier.
  • Bias, is designed to inspect the outputs generated by Language Learning Models (LLMs) to detect and evaluate potential biases. Its primary function is to ensure that LLM outputs remain neutral and don't exhibit unwanted or predefined biases.
  • Code, can be particularly useful in applications that need to accept only code snippets in specific languages.
  • Deanonymize, helps put back real values in the model's output by replacing placeholders.
  • JSON, dentifies and validates the presence of JSON structures within given outputs, and returns a repaired JSON if possible.
  • Language, identifies and assesses the authenticity of the language used in outputs.
  • LanguageSame, evaluates and checks if the prompt and output are in the same language.
  • MaliciousURLs, detects URLs in the output and analyzes them for harmfulness, such as detecting phishing websites.
  • NoRefusal, specifically designed to detect refusals in the output of language models. It can be especially useful to detect when someone is trying to force the model to produce a harmful output.
  • ReadingTime, estimates and manages the reading time of text content. It is particularly useful for applications where content length and reading time need to be controlled, such as in educational materials or time-sensitive reading platforms.
  • FactualConsistency,is designed to assess if the given content contradicts or refutes a certain statement or prompt. It acts as a tool for ensuring the consistency and correctness of language model outputs, especially in contexts where logical contradictions can be problematic.
  • Gibberish, is tailored to assess the outputs generated by LLMs to identify and flag gibberish or nonsensical content. Its key role is to ensure that LLM outputs are coherent and intelligible, devoid of meaningless or random text sequences.
  • Regex, is designed to sanitize outputs based on predefined regular expression patterns. It offers flexibility in defining patterns to identify and process desirable or undesirable content within the outputs.
  • Relevance,ensures that output remains relevant and aligned with the given input prompt. By measuring the similarity between the input prompt and the output, the scanner provides a confidence score, indicating the contextual relevance of the response.
  • Sensitive,serves as your digital vanguard, ensuring that the language model's output is purged of Personally Identifiable Information (PII) and other sensitive data, safeguarding user interactions.
  • Sentiment, is designed to scan and assess the sentiment of generated outputs. It leverages the SentimentIntensityAnalyzer from the NLTK (Natural Language Toolkit) library to accomplish this.
  • Toxicity, designed to assess the toxicity level of the content generated by language models, acting as a safeguard against potentially harmful or offensive output.
  • URLReachability, identifies URLs in the text and checks them for accessibility, ensuring that all URLs are reachable and not broken.

Agent 调试

Prompt(提示词) 测试

Prompt 单元测试

验证智能体内部的一个小部分,例如验证智能体在明显的情况下调用了特定的工具。适合测试晦涩的场景,容易验证预期行为。

Prompt 集成测试

从头到尾的复杂场景。这更有价值,因为它能告诉你“它实际上是否有效”。但这往往难以编写断言,因为结果是模糊的,例如对一个模棱两可的问题的回答。

示例

Ellipsis

Lessons from 15 months of building LLM agents

  • 评估与测试:作者强调了评估(evals)在开发LLM代理过程中的重要性。评估有两种类型:单元测试和集成测试。单元测试检查代理的某个小部分,而集成测试则验证复杂场景的整体表现。由于提示词(prompts)非常脆弱,甚至一个小的修改都可能导致输出质量下降,因此反复测试和验证是确保代理成功的关键。
  • 快照与缓存:为了应对LLM的非确定性和高成本,作者建议在开发代理时设置缓存。缓存不仅能使测试结果更具确定性,还能显著加快速度并降低成本。
  • 可观测性与日志记录:作者指出,尽管有许多高级的观测工具,但他仍然发现传统的日志记录更为有用。日志记录能够帮助开发者直观地理解代理的行为并诊断问题。
  • 提示词的管理与优化:作者认为提示词必须在版本控制中进行管理,尤其是对于复杂的代理而言。此外,他认为现有的LLM代理构建库(如Langchain)在实际应用中并不实用,代理往往需要大量的定制,因此自己编写代理逻辑可能更加高效。

PromptLayer

https://promptlayer.com/

PromptLayer不仅仅是一个调试工具,它还是一个强大的提示工程和管理平台,提供了多种关键功能,使得AI应用的开发和运营变得更加高效和智能化。

  1. 提示工程与管理:PromptLayer提供了强大的提示版本控制、批量处理和调试工具,使得团队能够更快地迭代和优化提示,确保AI模型能够提供更准确和上下文相关的响应。
  2. 可观察性与分析:通过详细的日志和元数据分析,PromptLayer帮助团队更好地理解AI的行为模式,发现潜在的问题并及时进行优化,减少了AI系统中的“黑箱”操作,增强了透明度。
  3. 可视化编辑与部署:PromptLayer的可视化编辑和自动部署功能,使得即使是非技术团队也能够高效地进行提示工程。这减少了对工程资源的依赖,提升了团队的整体生产力和灵活性。

PromptLayer 案例

案例:

公司名称挑战PromptLayer解决方案结果
Ellipsis快速扩展带来的高请求量导致调试效率低下使用PromptLayer的可观察性平台和元数据搜索功能,快速定位问题并通过UI进行调试调试时间减少90%,调试步骤减少90%,避免了大量工程资源消耗
ParentLab内容和工程团队需要快速迭代和部署AI提示通过PromptLayer的CMS和可视化编辑功能,简化提示迭代和部署流程提示部署速度提升10倍,节省400多个工程小时,提示质量显著提高
Speak.com非技术团队需独立迭代AI功能,但缺乏工程支持使用PromptLayer,内容和业务团队可以自主进行提示工程,减少开发时间产品开发和国际扩张中的大量时间和成本节省,关键功能迭代更快速灵活
ParentLab需要分析用户行为和优化AI响应,但Notion数据库效率低下PromptLayer提供日志和分析功能,帮助理解用户行为并持续改进AI响应提示迭代次数增加10倍,提示质量显著提高,节省数百个工程小时

Prompt Router

有诸多方法可以编程决定将用户的消息路由至哪个提示。

  1. 通用大型语言模型(LLM):最简单且最常见的方法是使用如GPT-4这样的大型语言模型。以下我们会采用这种方法。简而言之,创建一个提示模板,该模板接收用户消息,并返回用于路由的提示模板。
  2. 微调模型:通常,如果您能够可靠地获得GPT-4提示作为路由器,您可以微调一个较小的模型以节省成本和延迟。尝试对您的GPT-4输出进行GPT-3.5-Turbo的微调。
  3. 向量距离:生成嵌入向量非常快速且成本低廉(与常规完成相比)。您可以通过比较用户消息与可能分类的向量距离,轻松构建一个提示路由器。
  4. 确定性方法:有时您可以通过确定性解决方案来决定如何路由。也许您正在字符串中搜索一个关键词……
  5. 传统机器学习:最后但同样重要的是,分类是传统机器学习非常常见的一个应用场景。像决策树这样的工具可以帮助您构建比通用大型语言模型更便宜、更快速的提示路由器。

为了简化,我们将使用第一种选项,并为GPT-4编写一个作为路由器的提示。我们的提示模板将接收一个用户问题,并返回一个单词,指示适当的分类:“自我”、“新闻”或“编程”。在您的应用程序代码中,您可以使用这个输出来将问题映射到相应的提示模板。

Prompt 管理

这篇文章强调了在使用大型语言模型(LLM)开发AI产品时,提示管理的重要性。文章指出,尽管提示是使基于LLM的产品有效运行的关键,但往往被忽视, 导致产品演进过程中出现效率低下和瓶颈问题。

  1. 将提示与代码分离:将提示与主代码库分离存储,可以加快迭代速度,并使非技术人员更容易参与协作。使用提示管理系统(如PromptLayer)有助于简化这一过程。
  2. 模块化设计:文章借鉴了软件开发中的原则,建议将提示模块化为可重用的组件,如系统消息前言、少样本示例和指令。这种模块化方法简化了提示管理,使非技术人员更易参与。
  3. 工作区组织:保持提示在文件夹中的有序组织和控制访问,对于维护整洁高效的工作流程至关重要。良好的组织减少了风险,增强了协作效率。
  4. 协作策略:有效的提示管理需要建立编辑权限控制机制和版本冻结,以确保工程师与非技术人员之间的协作既稳定又安全。

A/B Testing Prompts

Prompt AB Test

那么,究竟如何进行提示语的A/B测试呢?

  • 首先,从小规模开始:先将新版本的提示语推向一小部分用户,例如5-10%的用户,或者仅仅是免费层级的客户。这样做可以限制风险,同时还能为您提供有价值的数据。
  • 逐步增加:在慢慢提高推广百分比的同时,密切关注用户指标。目标可以是10%、20%、40%,最终达到100%。注意任何红旗警告或负面影响。
  • 细分用户:并非所有用户都相同。考虑根据用户类型(免费用户与付费用户)、用户ID或公司等因素进行用户细分。这可以让您在全面推广之前,针对特定群体测试新版本。
  • 多种方法结合:A/B测试很有力,但不要仅限于此。将其与合成在线评估和严格的线下测试结合,以全面了解提示语的表现。
  • 迭代和优化:A/B测试是一个持续的过程。分析您的结果,对提示语进行调整,然后再次运行测试。持续的迭代是🗝️打造顶级提示语的关键。

关键在于要有条不紊、以数据为驱动,并且勇于尝试。通过从小规模开始,细分用户,通过对实际指标的测试和迭代,他可以充分发挥A/B测试在提示优化方面的潜力。

编程智能体编排:AI 自动化编程

编程智能体编排:理解 AI 自动化编程

示例

Tray.ai

Tray.io is now Tray.ai

为什么要进行改变?

自公司成立以来,Tray一直秉持着一个基本目标:赋予客户快速高效适应变化的能力。作为一款云原生、无服务器的iPaaS(集成平台即服务),我们演变成了一个多体验的集成和自动化平台。 Universal Automation Cloud的客户已经能够充分挖掘他们不断变化的应用程序和数据库的价值。如今,随着人工智能(AI)的兴起以及技术堆栈的迅速发展, 我们的敏捷平台再次转型,不仅能够更快、更有效地推动先进的AI功能,还优于那些在云计算和AI之前的iPaaS产品。

AI像地震波一样席卷了科技世界,带来了巨大的机遇,同时也暴露了传统系统的不足。企业在竞相部署全面的AI战略时,往往被过时的工具、 冗长的开发周期和僵化的集成平台拖累,还伴随着复杂的安全挑战。此外,新兴的AI技术从新的大型语言模型(LLM)到新兴的向量数据库,持续不断地涌现, 对IT部门构成了巨大压力,使其不得不评估并决定如何从中获得优势。因此,不难理解为何90%的企业在将AI集成到其技术堆栈中时面临挑战。为了应对这些变化, 并确保长期成功,企业所部署的AI战略需要具备速度、适应变化的能力,以及控制数据流动的能力。

Tray.ai提供了一个可组合的AI集成平台,团队可以利用AI增强的开发快速构建,在业务流程中灵活地注入AI,并控制AI应用的时间和方式, 我们称之为AI就绪的iPaaS。Tray.ai致力于以快速、灵活和安全的方式,将AI转化为卓越的商业表现。

快速:从原型到生产仅需数天

对于当今的企业来说,速度至关重要。开发应用程序和业务流程的旧方法——组建开发团队、制定项目计划、配置资源并开发六个月——已不再可行。企业技术堆栈中的高变更率,特别是AI,要求快速原型设计、部署和迭代。

在Tray.ai,我们一直倡导速度。我们的客户长期以来通过我们强大的低代码构建器,享受比传统技术更快的集成构建。通过我们单一的集成开发环境(IDE),他们可以在一个丰富的体验中利用流程自动化、数据集成、API管理和敏捷连接,无需浪费时间构建临时解决方案或调试附加代码。

现在,我们为企业提供了更快的速度。在过去的一年中,我们将AI的最佳功能与低代码的最佳功能结合在一起,扩展了我们的Merlin Build辅助开发工具,它提供基于LLM的增强开发。我们现在能够提供一个平台,让团队从原型到生产快速移动,将创意在几天内转化为部署的解决方案,而不是几个月。

以下是我们如何进一步扩展Merlin Build的增强开发功能,以新的强大方式让您更快地构建:

  • Merlin自动文档生成:再也不用浪费时间去弄清楚集成的工作原理或阅读过时的文档。我们新的基于GenAI的动态文档始终是最新的,自动提供逐步的详细信息。想象一下,每个集成都有完美的文档。
  • 建议的最佳实践:Merlin Build现在可以检查任何工作流程,并根据Tray.ai的最佳实践提出改进建议。这就像一个24/7在线的集成专家,确保业务流程优化以提高速度和效率。

灵活:轻松适应和扩展

AI领域变化的速度使得缺乏灵活性成为企业的负担。企业必须随创新的潮流而动,才能保持竞争力。然而,传统的iPaaS像一个锚一样,被固定不变,数年如一日。做出哪怕是最小的调整,对团队来说都代价高昂。

试想一下,面对如今企业可用的众多AI解决方案,任何组织如何能够知道哪种方案最能支持长期的AI战略。您今天选择的LLM很可能不会是您六个月后使用的LLM。在需求和技术快速变化的环境中,传统的刚性、长期规划和部署方法已过时。

灵活性是 Universal Automation Cloud 的核心,使其成为集中任何企业AI集成战略的理想平台。我们的平台一直易于适应不断变化的企业堆栈和业务需求。现在,我们进一步增强了其灵活性,使组织能够适应不断演变的AI格局,并满足新的AI业务需求。以下是具体实现方式:

将AI注入任何业务流程

在当今企业IT团队面临的核心挑战中,跟上最新的AI工具,确保与现有系统的顺利集成,以及安全地管理多样化的数据至关重要。这就是我们的AI Palette的用武之地——让将AI添加到任何流程变得比以往更加容易。IT团队可以快速原型AI解决方案,与最新的LLM轻松连接,在快速变化的环境中保持敏捷,并通过我们的灵活的原生向量数据库安全地处理数据,这是我们原生AI基础设施的一个示例。

  • 连接到任何LLM或ML服务 :使用我们内置的连接器,连接所有最新的LLM,从Anthropic到OpenAI,将GenAI添加到任何集成中。通过Tray的现代连接器开发工具包(CDK),轻松扩展这些能力,集成额外的服务、自定义API和新兴的AI工具。
  • 敏捷AI集成:不要让您的流程被AI锁定。Tray的原生AI功能使得在所有流程中添加、修改或移除AI变得简单,因此您可以在快速变化的环境中保持敏捷和与时俱进。
  • 灵活的向量数据库 :原生AI基础设施至关重要,因为它确保了AI在您的业务流程中的无缝、可扩展和安全的集成。这就是为什么我们在传统的基于表格和NoSQL的存储旁边,增加了原生向量数据库支持。现在,AI团队可以使用内置在我们平台和IDE中的向量数据库,安全地为RAG、搜索、推荐和文本生成自动化用例提供动力,或者按需连接到您选择的向量数据库。

Merlin功能

快速注入AI意味着让技术人员能够简单地将业务就绪的AI能力应用于他们的流程和集成。这些功能旨在改变AI开发和集成,技术人员可以在不受技术复杂性困扰的情况下添加AI和机器学习(复合AI)。

新的Merlin功能包括:

  • Merlin Extract智能文档处理(IDP):使用AI自动化每个文档处理流程。Merlin Extract能够理解最常见的文档格式,并让任何人智能地提取内容,如订单行、小计、地址等。
  • 文本摘要:自动总结从通话记录到客户评论和反馈的非结构化业务内容,形成正好适合的格式,并将其用于下游流程和分析。
  • 文本生成:按需创建结构化或非结构化文本,用于提供自动化响应或流入聊天、电子邮件、语音或其他面向客户或员工的流程。

安全:内置AI信任的企业核心

AI一出现,企业高管们立刻对安全性产生了担忧。他们问:“我们的数据安全吗?我们的客户数据安全吗?”随着每个AI驱动的产品被引入他们的技术堆栈,这种担忧也在增加。如今,AI信任已成为每个企业的核心关注点。

我们的Universal Automation Cloud构建在一个企业核心之上,提供坚如磐石的控制,确保与AI相关的集成和自动化数据和流程的安全性和合规性。为了解决这些安全挑战,我们引入了Merlin Guardian。

Merlin Guardian

快速将AI集成到您的业务中,同时不影响安全性,并在整个组织内最大限度地建立信任是基础。在我们的企业核心中,Merlin Guardian加强了我们的AI安全和合规能力,确保您的数据在每个步骤都受到保护。以下是Merlin Guardian如何保障您的AI集成的安全:

  • 数据遮蔽:通过内置的遮蔽功能,有选择地控制流经您的业务流程的所有敏感数据。
  • 完整的审计追踪:全面透明地了解在AI服务中共享了哪些信息。

编程智能体编排:自动化 CRUD

AI 辅助软件工程:评估与度量

榜单

Text2SQL

Text2SQL 榜单:Spider

SWE-Bench

https://www.swebench.com/

https://github.com/princeton-nlp/SWE-bench

AI 辅助软件工程:AI4SE 评估

AI4SE 度量评估

RAG 评估:Ragas

RAG Evaluation Using Ragas

评估 Ragas 所需的数据

根据 Ragas 的文档,您的RAG管道评估将需要四个关键数据点。

  • 问题:提出的问题。
  • 上下文:从您的数据中与问题意义最匹配的文本块。
  • 答案:您的RAG聊天机器人针对问题生成的答案。
  • 真实答案:问题的预期答案。

Ragas 评估指标

您可以在文档中找到每个指标的说明,包括其背后的公式。例如,忠诚度。一些指标包括:

  • 上下文精确度:使用问题和检索到的上下文来衡量信噪比。
  • 上下文召回率:使用真实答案和检索到的上下文来检查是否检索到了答案的所有相关信息。
  • 忠诚度:使用上下文和机器人答案来衡量答案中的陈述是否可以从上下文中推断出来。
  • 答案相关性:使用问题和机器人答案来评估答案是否解决了问题(不考虑事实性,但会惩罚不完整或多余的答案)。
  • 答案正确性:使用真实答案和机器人答案来评估机器人答案的正确性。 关于这些指标如何计算的具体细节可以在他们的论文中找到。

AI 辅助软件工程:AI4SE 度量

  • 更好:开发体验
    • SPACE Framework,如上手时间、构建时间、代码检视时间、开发者心情指数
  • 更快:价值交付。
    • 如价值交付周期/反馈周期
    • 如需求/变更Lead time等
  • 更好:交付质量
    • 如更高测试覆盖率
    • 更高的稳定性和可用性
    • 更好的代码质量和可维护性等
  • 更多:技能成长
    • 如掌握更多的技能如后端掌握前端开发,Dev掌握Ops等
    • 如更低的团队经验水平,1个TL能更多Junior团队成员等

ROI 计算

Semgrep ROI Caculator

金融行业案例:Ebay

链接:Cutting Through the Noise: Three Things We've Learned About Generative AI and Developer Productivity

目标

提升开发者生产力,提高软件开发效率和质量。

投资

  1. 商业产品投资:扩展使用GitHub Copilot。
  2. 微调和后训练LLM:开发eBayCoder,基于Code Llama 13B进行微调。
  3. 内部知识库:创建内部GPT,整合企业内部文档和数据源。

举措

  1. 利用商业产品(GitHub Copilot)
  • A/B测试
    • 测试组和对照组:300名开发者分为两组,一组使用Copilot,另一组不使用。
    • 结果
      • 代码接受率提高27%。
      • 生成文档准确率70%,代码准确率60%。
      • Pull Request(PR)创建到合并时间减少17%。
      • 变更Lead Time减少12%。
      • 代码质量保持不变。
    • 优势:自动生成代码、生成测试、自动填充重复代码。
    • 劣势:提示大小有限,处理大量代码时存在困难。
  1. 微调和后训练的LLM(eBayCoder)
  • 模型选择和微调
    • 使用Code Llama 13B作为基础模型,结合eBay代码库和文档进行微调。
  • 效果
    • 简化软件维护工作,如升级内部基础库和框架。
    • 减少代码重复,提供更多上下文。
    • 优势:处理更多内部数据,减少代码重复。
    • 劣势:需要大量内部数据进行微调。
  1. 内部知识库(内部GPT)
  • 系统架构
    • 使用检索增强生成(RAG)系统创建嵌入向量,并存储在向量数据库中。
    • 用户查询时,系统生成查询向量并与已知内容向量进行比较,找到最相关的内容和链接。
    • 使用LLM实例回答问题,若无法回答则返回"不知道"。
  • 效果
    • 提高任务完成速度。
    • 减少支持和会议请求。
    • 优势:提供高效和相关的答案,减少搜索时间。
    • 劣势:偶尔会生成无意义的答案,需要通过用户反馈(RLHF)不断改进。

AI 辅助软件工程:未来展望

AI 辅助软件工程:参考资料