大模型效能工具之智能CommitMessage

news2024/11/15 4:25:51

01 背景

随着大型语言模型的迅猛增长,各种模型在各个领域的应用如雨后春笋般迅速涌现。在研发全流程的效能方面,也出现了一系列贯穿全流程的提效和质量工具,比如针对成本较高的Oncall,首先出现了高质量的RAG助手;在开发阶段的Copilot、Comate、Tabnine等辅助编程应工具;在测试阶段,也有缺陷检查、安全合规检查、智能Code Review等工具;哪怕在交付阶段,也有替代人工的自动化Agent…

当使用git commit提交代码时,需要写繁杂的CommitMessage,有时候写了后却不符合提交规范被hook,有时候还被CodeReview的同学点评写不到点上…智能CommitMessage就是这样一个小助手,帮你按照提交规范自动生成符合规范的CommitMessage。

以百度APP 的提交规范为例,规范包括提交类别、产品版本、需求卡片、变更摘要等,其中类别又包括:功能、更新、优化、提测、上车、Merge、FixBug等,手动抒写较为复杂。

按照CommitMessage的组合标准,可以分为两个部分:规范格式 + 变更摘要:

图片

CommitMessage组成部分

  • 普通摘要类:提交规范格式 + 变更摘要
  • FixBug类:提交规范格式 + 变更摘要(包括bug原因、影响、修复方式等)

其中运用大模型能力生成变更摘要部分,而提交规范格式及其他标签由个性化插件定制,即可对不同业务线/产品线可定制符合提交规范的CommitMessage。

智能CommitMessage的最终使用效果如下:查看原文

git aicommit 用法示例

下面就以智能CommitMessage为例,介绍下大模型效能工具开发流程,主要包括:

  • 简单的功能设计
  • 应用指标和模型评估指标
  • 大模型数据处理过程
  • 模型性能优化的几种方式

02 功能与设计

用户入口一:git aicommit

Git是高效便捷的版本控制系统,虽然百度APP移动端已经多仓库化,随着组件化进程的完善,有至少有一半的需求不需要跨仓库提交而使用Git。

用户入口二:mgit aicommit

MGit (https://github.com/baidu/m-git)是百度自研的一套开源的、基于Git的多仓库管理工具,针对多仓库的应用场景安全地、高效的管理多个Git仓库,在基础版本之上增加MGit插件即可扩展或者修改原命令。

对入口的基本要求:

  1. Git/MGit入口的使用不影响原有git/mgit commit功能的使用,只是能力扩展
  2. 保证Git和MGit的入口分离的同时,保证功能统一,低成本维护

处理方式:抽象实现共用模块git-aicommit,该模块由MGit插件和Git alias命令直接调用,开发语言选型ruby,便于 MGit 插件直接调用。

git-aicommit模块:提取所有提交仓库中Git暂存区内的变更内容,请求模型服务生成Commit Message。

  • MGit/Git入口,即用户使用入口,对于MGit插件可以参考MGit如何扩展(https://github.com/baidu/m-git);Git Alias按如下配置即可:
# 给 git 添加 Alias:git aicommit
$ git config --global alias.aicommit '!f() { ruby -e '''require "git-aicommit"; MGit::GitAICommit.run(ARGV);''' -- "$@"; }; f'
  • 个性化插件:提交规范的格式定制,任何不同的提交规范均可定制为独立的插件,详细参考下面自定义提交规范章节。
  • 模型服务:接受git-aicommit模块的请求,调用LLM生成CommitMessage摘要内容,加载对应的个性化插件生成最终的CommitMessage。

03 评估指标

管理学之父彼得·德鲁克说过:“If you can’t measure it, you can’t manage it.”。

度量指标对于模型选择、后续Prompt调优以及SFT都至关重要,因为它决定了优化的标准。

生成CommitMessage时,既需要理解变更的代码,也需要生成对应的摘要、评估影响等,生成式大模型适合此类任务,当前生成式大模型在市面上也百花齐放,经过综合评估使用成本(包括数据管理、部署运维、性能调优、Prompt和模型评估)、生成质量、安全风险等方面的考虑,我们选择了百度智能云千帆平台的ERNIE4(文心4)。

针对此类摘要任务,常用的度量指标有BLEU Score、ROUGE Score、BERT Score、PPL、MSE等,结合生成CommitMessage的任务特性,最终确定模型和产品的核心指标:

  • 模型性能指标:MSE(Mean Squared Error,均方误差),用于衡量生成的文本序列与参考CommitMessage的文本序列之间的语义相似度;
  • 用户使用指标:AR(Acceptance Rate,直接采纳率),也叫用户直接满足度,针对模型服务生成的CommitMessage,用户直接采纳的次数相对于总的使用次数的占比

均方误差MSE(Mean Squared Error)

参考CommitMessage的文本序列,指高质量的、简洁的、准确的、标准的CommitMessage,客观标准是至少包括:为什么修改(Why)、改了什么(What)、影响面(可选),主观标准是人工筛选并提取。

根据定义,计算MSE即计算两段文本的语义相似度差值,简单的分为如下三个步骤:

1.文本Embedding向量化:

  • 将两段文本转换为向量表示。大模型时代Embedding的方式太多太多了,这里依然直接选用了千帆的Embedding方式。

2.向量差异计算:

  • 计算两段文本的向量表示间的差异或距离时,我们选择使用余弦相似度;尽管欧几里得距离和马氏距离也是常用的方法,但针对CommitMessage这种长度不一致的向量时,余弦相似度表现更为准确。

3.均方误差计算:

  • 将差异或距离平方,然后计算平均值以得到均方误差。
  • 图片
  • 其中,xi 和 yi 是两段文本在第 i 个维度上的表示,n 是维度数量。

本文多次提交两个概念:

参考CommitMessage:可以是RD生成已提交入库的,也可以由大模型生成、经过人工标注的保证质量的CommitMessage,作为评估的标准yi

生成CommitMessage:由大模型生成的CommitMessage,评估输入的判定项xi

直接采纳率AR(Adoption Rate)

总的使用次数包括3个结果:

  • 直接采纳数 CA
  • 编辑采纳数 CE
  • 拒绝数 CR

图片

04 数据处理

大模型应用开发为了更好的性能(包括生成质量、效率、准确度、采纳率),数据处理的成本投入较高,通常占据整个应用开发投入的相当大的比例,有时甚至可能超过模型训练和调优的工作量。总之,有效和高效的数据处理是提升模型性能的关键因素,因此在项目计划和资源分配中应给予足够的重视和投入。

数据处理的目标就是管理(增删改/标查)好数据集,产物是各类数据集,数据集的最终应用场景是模型的性能优化(模型选择、Prompt优化、SFT),也就是说,如果不做性能优化,就可以不用做数据处理。

数据集与性能优化的关系如下:

  • 评估集,模型选择、Prompt调优、SFT后都需要评估集对本次调优进行评估,是否比之前的好,是否达到调优的效果
  • 训练集,指用于SFT的标注数据,根据特征从总数据集中筛选
  • 验证集,验证集是用来调整模型超参数,避免过拟合或欠拟合
  • 测试集,SFT后测试是否达到SFT的目的,比如针对某个异常case评估其泛化能力
  • 异常集,标注环节明确的低质量的CommitMessage数据,特别是大模型生成未被直接采纳的数据

这里介绍下大体的过程及其作用,细节不做展开:

  • 定义数据结构:模型数据(需求/bug卡片标题、变更数据)、参考CommitMessage、类别数据(是否bug、变更行、仓库数)、辅助分析数据(产品线、平台、作者、Topic)等
  • 数据采集:来源于:①线上模型服务生成的CommitMessage;②存量RD已提交入库的CommitMessage;③其他开源数据集
  • 数据清洗:去噪、去重等处理,确保数据的质量和可用性
  • 标注与注释:标注本条数据作为参考CommitMessage的质量,其他辅助分析信息
  • 分类与管理:抽样配比、过滤筛选、查看等

根据我们当前的数据体量,选择了Pandas(https://pandas.pydata.org/)作为数据处理工具,它对小规模数据和单机环境提供了够用的数据处理和分析功能。然而,随着数据体量的逐步增大,Spark(https://spark.apache.org/)将是一个不错的选择。

05 性能优化

性能优化的目标是提升性能指标,包括核心指标均方误差MSE和生成效率,进而提升用户直接采纳率AR,手段包括如下三种:

  • 停止标记(Stop Token),可提升生成效率
  • Prompt优化,可优化MSE指标和提升生成效率
  • SFT可优化MSE指标

5.1 停止标记

当模型对Prompt理解不完全时,容易生成多余的解释或注意事项等无效内容,生成更多的Token导致生成效率降低(生成效率与生成的Token长度直接相关),而所有Transformer模型中都设计有停止标记,比如智能CommitMessage里调用模型的输出是一个Markdown的json,以“%STOP%”结尾,可指定停止标识为“%STOP%”以提高生成效率。

5.2 Prompt优化

简单说Prompt优化就是设计和优化输入Prompts以获得期望的输出。看似一个简单的NLP任务,却又叫Prompt工程?因为需要让大模型更好的理解期望的需求,确实涉及多学科的知识,比如融合语言学、心理学、计算机科学、数据科学,也包括整套工程方法:系统设计、实验设计、质量控制、项目管理等等方面。智能CommitMessage里涉及的两个优化点:

  1. 限制输出内容,明确要求

CommitMessage调用模型的输出要求是Markdown的json,如果模型输出不是正常的json将导致解析异常,此时在Prompt中明确要求『请仅输出内容,不要做任何解释』可避免生成无效内容,提高生成效率和准确性。

  1. Few-shot

Prompt优化里有个优化在限制输出样式的情况下非常有效 --Few-shot,以示例让大模型理解并限制输出样式,要求输出一个Markdown 的多行的 json 数据,样例:

按以下格式输出CommitMessage,只是一个markdown的代码片段,包含在"```json" 和 "```"内,『请仅输出内容,不要做任何解释』:
```json
{
    "summary": string  // 少于30字的中文,简洁的、准确的描述Git Commit Message
    "reason": string  // 分析修复方式,详细描述这个bug出现的具体原因,可以引用代码,少于60字
    "fixup": string  // 分析修复方式,简洁、准确的描述修复方式,可以引用代码,少于30字
}
```

这里的样例不是一个标准的json格式(多行换行时缺少“,”),大模型可能按照该格式输出,也可能按照正确的json格式输出,所以存在一个异常问题的不确定性,可通过完善该Few-shot完全避免该问题:

按以下格式输出CommitMessage,只是一个markdown的代码片段,包含在"```json" 和 "```"内,『请仅输出内容,不要做任何解释』:
```json
{
    "summary": string,  // 少于30字的中文,简洁的、准确的描述Git Commit Message
    "reason": string,  // 分析修复方式,详细描述这个bug出现的具体原因,可以引用代码,少于60字
    "fixup": string  // 分析修复方式,简洁、准确的描述修复方式,可以引用代码,少于30字
}
```

这里有个类似的概念:Prompt Tuning,Few-shot 和 Prompt Tuning都是优化和调整大型语言模型输入提示的方法,但有着本质上的区别:

附上智能CommitMessage的部分Prompt(持续优化中):

通俗易懂的角色描述:基于需求描述和实现该需求的git diff变更代码,自动生成规范的git提交信息。 
需求描述的标题如下:{{%title}}

git diff变更代码如下:
(DIFF-START)
{{%git_diff}} 
(DIFF-END)

任务拆解
1.  解析需求标题: 
提取关键信息,如功能点、问题点等。
对文本进行清洗,去除无关字符和格式。
2.  分析git diff变更代码:
识别变更的文件和代码块。
分析代码变更的类型(如新增、修改、删除等)。
3.  生成Commit Message:
结合需求标题以及代码变更分析,编写Commit Message。 
确保提取的内容符合对应项的要求,如“summary: 少于30字的中文,简洁的、准确的描述Git Commit Message”等。
4.  验证Commit Message: 
检查Commit Message是否清晰、准确。
5.  按以下格式输出CommitMessage,只是一个markdown的代码片段,包含在"`json" 和 "`"内,『请仅输出内容,不要做任何解释』:
```json
{
  "summary": string  // 少于30字的中文,简洁的、准确的描述Git Commit Message
}
```%STOP%

5.3 SFT

因为文心4的模型能力已经有非常出色的生成能力,在这种大模型上做SFT成本非常高,所以一般会采用ERNIE-lite版本或者ERNIE-Speed版本,但是性能稍逊一筹,那如何保证在ERNIE-Speed版本中SFT后既能不降低整体性能,又能优化低质量case?

这里可以采用MoE(Mixture of Experts)的策略,用一个分类器来结合ERNIE4 + (ERNIE-Speed + SFT)各自的优势,即请求优先经过一个分类器,根据请求的特征进行分类请求ERNIE4或者经过SFT后的ERNIE-Speed模型,如下图示例:

部署前记得SFT评估数据集的全量评估,MSE优于线上保证本次SFT后的ERNIE-Speed模型比上次的更好。

SFT的全过程应该包含四个步骤:

  1. 确定目标:优化某个/某类低质量的数据case,微调后达到评估多少分值
  2. 数据准备:基于该case提取低质量case的特征,向数据集里筛选出训练集、验证集和测试集
  3. SFT过程:如上图所示
  4. 评估部署:根据抽样配比的评估集进行全量评估,保证本次SFT后的ERNIE-Speed模型比上次的更好

06 自定义提交规范

由于大模型只生成核心的变更摘要或者Fixbug的相关信息,而最终需要组合成各式各样的提交规范格式,所以可以将变化抽象为接口,可扩展python package实现接口达成自定义符合提交规范的CommitMessage,按需动态加载实现的插件。

抽象接口如下:

from abc import ABC, abstractmethod

class IPluginHook(ABC):
    """插件实现的接口定义"""
    @abstractmethod
    def hook_prepare(self, ctx):
        """准备"""

    @abstractmethod
    def hook_is_fix_bug(self, ctx) -> bool:
        """是否fixbug的提交类型,默认false"""

    @abstractmethod
    def hook_language(self, ctx) -> Language:
        """生成语言,默认中文"""

    @abstractmethod
    def hook_generate_variables(self, ctx):
        """生成模板的变量"""

    @abstractmethod
    def hook_generate_message(self, ctx) -> str:
        """根据模板和变量,生成CommitMessage
        @warning: 该方法插件必须实现,否则将报出异常
        """

加载某个插件的某个版本时,根据pkg_resources判定是已加载,然后配合 importlib进行import_module或者reload即可实现动态加载插件

def __install_plugin(pkg_name: str, version: str):
    """安装插件"""
    subprocess.check_call([sys.executable, '-m', 'pip', 'install', f"{pkg_name}=={version}"])
    return __load_module(pkg_name, force=True)

def __load_module(pkg_name: str, force: bool = False):
    """加载module"""
    module_name = __module_name(pkg_name)
    loaded_module = sys.modules.get(module_name)
    if loaded_module is not None:
        if force:
            m = importlib.reload(loaded_module)
            importlib.reload(pkg_resources)
            return m
        return loaded_module
    m = importlib.import_module(module_name)
    importlib.reload(pkg_resources)
    return m

07 未来

大模型对各类语言的代码理解上展现了卓越的能力,但对专有词汇、特定配置、固定格式等的理解依然存在不足,都需要合适的数据集来逐步优化;并且git diff获取的变更内容有限,受限于模型Token的限制,理解时缺少代码的上下文、依赖关系的关联导致生成质量存在瓶颈,结合RAG或许是一个较好的方式;使用入口的交互性、自定义提交规范都可以更AI,总之:AI Native 尚未成功,同志仍须努力。

——————END——————

参考资料:

[1] LangChain:https://www.langchain.com/

[2] git:https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases

[3] pandas:https://pandas.pydata.org/

[4] Spark:https://spark.apache.org/

[5] 百度千帆:https://console.bce.baidu.com/qianfan/overview

[6] Prompt工程 大模型的应用与实践:https://zhuanlan.zhihu.com/p/668200325

推荐阅读:

基于afx透明视频的视觉增强前端方案

百度一站式数据自助分析平台(TDA)建设

浅析如何加速商业业务实时化

登录系统演进、便捷登录设计与实现

一文带你完整了解Go语言IO基础库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1685316.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云原生Kubernetes: K8S 1.26版本 部署KubeSphere

目录 一、实验 1.环境 2.K8S 1.26版本部署HELM 3.K8S 1.26版本 部署KubeSphere 4.安装KubeSphere DevOps 二、问题 1.如何安装Zadig 2.扩展插件Zadig安装失败 3.calico 如何实现不同node通信 4.如何清除docker占用的磁盘空间 5.如何强制删除资源 6.namespace删除不…

linux命令中arj使用

arj 用于创建和管理.arj压缩包 补充说明 arj命令 是 .arj 格式的压缩文件的管理器,用于创建和管理 .arj 压缩包。 语法 arj(参数)参数 操作指令:对 .arj 压缩包执行的操作指令;压缩包名称:指定要操作的arj压缩包名称。 更多…

非关系型数据库NOSQL

文章目录 1. NOSQL 概述2. 相关理论基础2.1 一致性2.2 分区2.3 存储分布2.4 查询模型 3. NOSQL 数据库的种类3.1 文档存储3.2 键值存储3.3 列存储3.3 图存储 4. NOSQL 应用案例和新技术4.1 HBase 数据库4.2 云数据库 GeminiDB 非关系型的数据库 NOSQL (Not Only SQL)是对不同于…

2024.05.23 学习记录

1、 react hooks 面经复习 2、xiaolin coding 计算机网络 复习 3、组件库 subMenu、test测试、tabs组件初步开发完成 4、代码随想录刷题:动态规划 01背包 all

sharded jedis pipelined 执行后 数据并未存入redis

前言 因为历史原因,在某个同步菜单操作的方法中先清除缓存,然后在初始化缓存。本来很正常的逻辑,但是这个清除是db查询获取所有的菜单 然后循环一条条删除 然后在db查询有效的菜单操作 在循环一条条插进去 经统计这个菜单操作大概有个7千个 …

实战Java虚拟机-高级篇

一、GraalVM 什么是GraalVM GraalVM是Oracle官方推出的一款高性能JDK,使用它享受比OpenJDK或者OracleJDK更好的性能。GraalVM的官方网址:https://www.graalvm.org/官方标语:Build faster, smaller, leaner applications。 更低的CPU、内存…

化简资源分配图判断是否发生死锁

目录 1.资源分配图的概念 2.判断是否发生死锁 1.资源分配图的概念 资源分配图表示进程和资源之间的请求关系,例如下图: P代表进程,R代表资源,R方框中 有几个圆球就表示有几个这种资源,在图中,R1指向P1&a…

【加密与解密(第四版)】第十五章笔记

第十五章 专用加密软件 15.1 认识壳 15.2 压缩壳 UPX、ASPack、PECompact 15.3 加密壳 ASProtect(压缩、加密、反跟踪代码、CRC校验、花指令)、Armadillo(穿山甲)、EXECryptor、Themida 15.4 虚拟机保护软件 虚拟机引擎(编译器解释器虚拟CPU环境指令系统&#xff…

后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操

之前的SQL语句是基于注解 以后开发中一般是一个接口对应一个映射文件 书写映射文件 基本结构 框架 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.or…

嵩山是颍水的嵩山

颍水对于嵩山具有特别重要的意义&#xff0c;嵩山的水流大多数汇入了颍河&#xff0c;颍河流域约占登封市总面积88%&#xff0c;从这个角度讲&#xff0c;嵩山就是颍水的嵩山。 再看环嵩山地区&#xff0c;即“嵩山文化圈”&#xff0c;学者们按黄、淮、济分为三个水系区。黄河…

解决IE11通过主机名访问和IP地址访问,CSS渲染效果不一致问题

软件环境 spingboot:版本2.6.13 浏览器&#xff1a;IE11 问题描述 html用css渲染&#xff0c;浏览器输入IP地址访问&#xff0c;和输入主机名访问&#xff0c;效果不一样&#xff0c;如下图&#xff1a; IP地址访问才是我想要的效果&#xff0c;主机访问菜单半透明向下箭头…

如何让大模型更聪明?

如何让大模型更聪明&#xff1f; *随着人工智能技术的飞速发展&#xff0c;大模型在多个领域展现出了前所未有的能力&#xff0c;但它们仍然面临着理解力、泛化能力和适应性等方面的挑战。那么&#xff0c;如何让大模型变得更聪明呢&#xff1f; 方向一&#xff1a;算法创新 …

Web3空投流程分享:如何操作及注意事项

空投&#xff08;Airdrop&#xff09;指通过向特定用户群体免费分发代币&#xff0c;项目方希望能够吸引更多的用户和关注。对于许多刚刚接触加密货币和区块链的新手来说&#xff0c;都会疑惑空投的流程究竟是什么样的呢&#xff1f;又该如何参与其中&#xff1f;本文将为您详细…

AI智能体|使用扣子Coze基于IDE创建自定义插件

大家好&#xff0c;我是无界生长。 在使用Coze的过程中&#xff0c;有些个性化场景无法通过插件商店已有的插件满足&#xff0c;这个时候就需要通过自定义插件的方式来实现业务需求。下面将通过一个实际案例来简单介绍下如何使用Coze基于IDE创建自定义插件&#xff0c;完成在Co…

SpringCloud微服务02-微服务拆分-注册中心-OpenFeign-网关路由-网关登录校验-配置管理

一、认识微服务 1.单体架构 当高并发功能和重要功能都在同一个Tomcat服务器&#xff0c;当高并发的时候&#xff0c;重要的功能接口就会受到影响。 2.微服务 跨服务就需要一些技术栈 3.SpringCloud 二、微服务拆分 1.熟悉黑马商场 2.服务拆分原则 什么时候用微服务&#xf…

HTML+CSS+JS 扩散登录表单动画

效果演示 Code <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,us…

Grafana HTML Panel展示post获取后数据

<!DOCTYPE html> <html> <head><title>API 数据表格展示</title><script src"https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body><table id"data-table" border"1&qu…

每日一题《leetcode--143.重排链表》

https://leetcode.cn/problems/reorder-list/ 这道题我们可以用两种方法 第一种&#xff1a;用数组存储该链表&#xff0c;然后通过访问数组下标的方式来改变该链表的排列方式。 void reorderList(struct ListNode* head) {第一种方法&#xff1a;用线性表存储该链表if(head …