大模型效能工具之智能CommitMessage

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基础库

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【二叉树】:LeetCode:100.相同的数(分治)

🎁个人主页:我们的五年 🔍系列专栏:初阶初阶结构刷题 🎉欢迎大家点赞👍评论📝收藏⭐文章 1.问题描述: 2.问题分析: 二叉树是区分结构的,即左右子树是不一…

数据库DCL语句

数据库DCL语句 介绍: DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访 问权限。 管理用户: 查询用户: select * from mysql.user;创建用户: create user 用户名主机名 identified by 密码;修改用…

基于开源ATmega8 无感BLDC程序移植到ATmega328PB

基于开源ATmega8 无感BLDC程序移植到ATmega328PB 🔖基于Atmel Studio 7.0开发环境。🥕开源原项目资源地址:https://svn.mikrokopter.de/websvn/listing.php?repnameBL-Ctrl&path%2F&📍原理图和PCB资源 BL-Ctrl v2.0 in E…

Keli5烧写STM32程序时出现ST-LINK USB communication error错误(USB 通信错误)

1错误原图 2错误原因 前提驱动安装正确 原因1 usb接触不良(极少出现) 解决方法 更换USB线 还不行连下载器一起更换 原因2(出现概率比较大) 下载器的固件出现问题或下载器固件版本与Keli5的版本不匹配 解决方法 在Keli5的…

【python】python tkinter 计算器GUI版本(模仿windows计算器 源码)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

创建带有公共头部的Electron窗口

创建带有公共头部的Electron窗口 创建一个公共头部的html文件 1.我们在项目根目录创建一个名为app-header的文件夹 2.在app-header创建一个文件名为header.html的文件 结构如下&#xff1a; 基本结构和脚本如下 <body> <div class"header"><div c…

基于STM32+NBIOT(BC26)设计的物联网观赏鱼缸

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目模块组成 1.2 设计思路 二、(硬件控制端)硬件选型2.1 STM32开发板2.2 PCB板2.3 USB下载线2.4 NBIOT模块2.5 杜邦线&#xff08;2排&#xff09;2.6 稳压模块2.7 电源插头2.8 水温检测传感器2.9 水质检测…

Python 中别再用 ‘+‘ 拼接字符串了!

当我开始学习 Python 时&#xff0c;使用加号来连接字符串非常直观和容易&#xff0c;就像许多其他编程语言&#xff08;比如Java&#xff09;一样。 然而&#xff0c;很快我意识到许多开发者似乎更喜欢使用.join()方法而不是。 在本文中&#xff0c;我将介绍这两种方法之间的…

计算机网络(1

网络初识 目录 网络初识一. 网络分类1. 局域网LAN(Local Area Network):2. 广域网WAN(Wide Area Network): 二. 组建网络的基础设备1. 路由器2. 交换机 三. 标识符 协议 (protocol)一. 协议分层1. 分层的好处2. OSI七层分层3. TCP/IP五层模型(或四层) 模型(1. 物理层(可不算)(2…

从零开始:手把手教你使用Python实现PDF到Excel的转换

来百 在日常工作和学习中&#xff0c;我们经常会遇到需要将PDF文件中的数据提取到Excel表格中的情况。可能是为了进行数据分析、报告生成或者其他目的。虽然手动复制粘贴是一种方法&#xff0c;但对于大量的数据来说&#xff0c;这种方式显然效率太低。幸运的是&#xff0c;Py…

摸鱼大数据——Hive基础理论知识——Hive基础架构

1、Hive和MapReduce的关系 1- 用户在Hive上编写数据分析的SQL语句&#xff0c;然后再通过Hive将SQL语句翻译成MapReduce程序代码&#xff0c;最后提交到Yarn集群上进行运行 2- 大家可以将Hive理解成有道词典&#xff0c;帮助你翻译英文 2、Hive架构 用户接口: 包括 CLI、JDBC/…

ISCC——AI

得到一个T4.pyc 回编译一下 得到下面代码 import base64def encrypt_and_compare(user_input, offset_str, target_base64):if len(user_input) ! 24:return Please enter a string with a length of 24encrypted Nonefor i, char in enumerate(user_input):offset int(off…

自然资源-各级国土空间总体规划的审查要点及流程总结

自然资源-各级国土空间总体规划的审查要点及流程总结 国土空间规划是对一定区域国土空间开发保护在空间和时间上作出的安排&#xff0c;包括总体规划、详细规划和相关专项规划。 国土空间规划管理是国土空间规划中重要的一环。中共中央、国务院发布《关于建立国土空间规划体系…

C++ Primer Plus第十八章复习题

1、使用用大括号括起的初始化列表语法重写下述代码。重写后的代码不应使用数组ar。 class z200 { private:int j;char ch;double z; public:Z200(int jv,char chv&#xff0c;zv) : j(jv), ch (chv), z(zv){} };double x 8.8; std::string s "what a bracing effect ! …

添砖Java(十一)——常见类的使用Object,Math,System,BigDeciaml,包装类

目录 object&#xff1a; toString&#xff1a; equals: ​编辑 Math&#xff1a;​编辑 System: BigDecimal: 基本数据的包装类&#xff1a;​编辑 object&#xff1a; 我们知道&#xff0c;所有的类都是间接或直接继承了object类。然后object里面有几个用得很多的方法…

使用printf的两种方法,解决printf不能使用的问题

使用printf的两种方法&#xff0c;解决printf不能使用的问题 一、微库法 我们使用printf前要加上重定向fputc //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)0);//循环发送,直到发送完毕 USART1->DR (uint8_t) ch; return…

【JVM实践与应用】

JVM实践与应用 1.类加载器(加载、连接、初始化)1.1 类加载要完成的功能1.2 加载类的方式1.3 类加载器1.4 双亲委派模型1.5自定义ClassLoader1.6 破坏双亲委派模型2.1 类连接主要验证内容2.2 类连接中的解析2.3 类的初始化3.1 类的初始化时机3.2 类的初始化机制和顺序3.2 类的卸…

RedHat9 | DNS剖析-配置辅助DNS服务器

一、实验环境 1、辅助域名DNS服务器 DNS通过划分为若干个区域进行管理&#xff0c;每一个区域由1台或多台DNS服务器负责解析&#xff0c;如果仅仅采用1台DNS服务器&#xff0c;在DNS服务器出现故障后&#xff0c;用户将无法完成解析。 辅助DNS服务器的优点 容灾备份&#x…

Star-CCM+中滞环的实现—场平均监视

前言 前文有介绍过通过更新事件来实现滞环,但是更新事件的方法比较繁琐,应用起来比较困难,本文将介绍一种简单的方法来实现滞环功能。即通过场平均监视来实现,具体方法如下: 一 创建场平均监视 首先在检测量下创建“场平均监视”,具体操作步骤如下图所示: 二 创建质量…