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

news2024/9/24 19:15:05

背景

2023年CodeFuse完成了百亿级别的代码大模型从0到1的预训练,配合指令微调、量化部署等一系列配套技术,成功将AI大模型能力应用到多个下游研发场景,助力生产提效。在众多下游产品中,CodeFuse代码补全插件直接触及研发过程中最核心的编码场景,因此对开发效率的影响最显著。目前,CodeFuse代码补全插件是CodeFuse系列产品中用户数量最多、留存率最大,调用AI能力最多的产品。

目前,大部分代码语言模型在预训练阶段以文件为基本单位,随机选择代码文件拼接固定长度后组成训练样本。常见的代码评测数据集(HumanevalX、MBPP)也以单文件为主:基于待补全位置(Task Hole)的前缀(Prefix)使用Left-to-Right方式推理,或者同时使用前缀(Prefix)和后缀(Suffix)采用FIM(Fill In the Middle)方式推理。然而,实际的开发场景通常以代码仓库(Repository)为基本单位。在目前常见的业务设计模式下,大量与当前编辑文件存在依赖关系的内容散落在仓库内的的其他文件中,模型仅使用当前编辑文件内容预测会存在上下文不足的问题,从而导致补全结果存在幻觉、不准确等问题。目前,比较常见的解决思路是使用RAG的方法抽取一定代码片段作为上下文指导模型推理,但此方案同时会带来"上下文-延迟困境"的挑战。即丰富的上下文带来的效果提升和更长的提示内容增加的推理时间之间的权衡,这种权衡在IDE场景中可能会影响用户的实际体验。

为了解决上述问题,本文提出一种仓库级别代码补全框架RepoFuse:通过对实际编程的总结抽象,我们的方法从仓库中抽取了两种关键的跨文件上下文:基于代码相似性分析的相似上下文(Similar Context),用于识别功能相近的代码段;以及语义上下文(Semantic Context),提供类别分类和API交互的语义理解。然而,如此大量的信息可能导致模型的输入过于冗长,影响推理生成的效率。为此,RepoFuse采用了一种基于相关性引导的上下文选择策略(Relevance-Guided Context Selection)指导模型Prompt的构建。这种技术有选择地筛选出与当前任务最相关的上下文,将上下文精炼为简洁的Prompt,既能适应有限的上下文长度,又能确保高完成度的准确性。本文使用常见的开源代码模型在CrossCodeEval的Java和Python数据集上进行了实验,结果表明在完全匹配指标(Exact Match)上RepoFuse有3.01到3.97的提升(与当前主流开源工具的SOAT对比)。

相关工作

目前业界的相关工作主要沿用RAG的思路,代表工作如下表所示。具体来说,每一个方法需要回答以下三个问题:搜什么、怎么搜以及怎么用:

名称

搜什么

怎么搜

怎么用

RLPG

启发式搜索规则

判别模型选择搜索规则

Prompt Engineering

RepoFusion

同RLPG

同RLPG

Fusion-In-Decoder

ReACC

外部知识库相似片段

相似度搜索

Prompt Engineering

RepoCoder

仓库内相似片段

生成 + 相似度迭代搜索

Prompt Engineering

CrossCodeEval

仓库内相似片段

相似度搜索

Prompt Engineering

RepoBench

语义依赖信息

AST

Prompt Engineering

Cocomic

语义依赖信息

Dependency Graph

Fusion-In-Decoder

RLPG首先定义了63种启发式搜索规则,每一种搜索规则由Prompt Source和Prompt Context Type两部分组成。在补全时,使用一个分类模型判别最适合当前场景的搜索规则,为模型提供Example Specific的Context。 RepoFusion是RLPG的延续工作,差异点在Context信息的使用方式上。RepoFusion采用了Fusion-In-Decoder的模型结构使用Context信息,具体如图1所示:将不同的Context信息并行使用Encoder模型编码成Embedding表示,再将这些Embedding信息拼接起来使用DeCoder模型进行推理预测。相比目前常见的Decoder-Only的模型结构,Fusion-in-Decoder将Context信息压缩成Embedding后再处理,理论上可以使用更多Context信息,但使用此结构需要额外准备数据集进行训练。

图1:RepoFusion流程

ReACC使用待补全的代码在离线收集好的代码数据库中进行相似度检索,并利用相似片段辅助模型补全。RepoCoder提出了迭代式的“检索-生成”框架:先进行第一次检索,利用LLM生成一次补全结果。再使用生成后的结果进行二次检索并指导模型生成,反复循环直至迭代结束。结果表明迭代式搜索策略比直接搜索在效果上更好,但迭代搜索必然会带来推理耗时翻倍,难以直接用于真实的补全场景。此外,RepoCoder还提出了仓库级别代码补全数据集RepoEval,支持行、片段、方法级别的补全任务。

图2:RepoCoder流程

CrossCodeEval和RepoBench分别提出了仓库级别代码补全的BenchMark,区别在于CrossCodeEval使用仓库内相似代码片段辅助模型补全,而RepoBench则使用AST分析出当前文件的Import内容,并将其视作补充上下文。

CoComic使用程序分析领域的Dependency Graph搜索,图中的节点为仓库中不同粒度程序片段的抽象表示(File、Class、Method、Global Variable),边则是这些节点之间的程序依赖关系。在补全时,首先定位到待补全片段所在的节点,然后将其邻居节点视作补充上下文。由于节点数量众多,无法全量放置到Prompt中,CoComic也采用了类似Fusion-in-Decoder的方法进行训练。

方法

我们的思想源于对软件开发实践的观察:当程序员开始向一个仓库贡献代码时,必须展现两项基本技能。首先,程序员必须熟练掌握仓库的架构,包括跨文件的模块、库和API。对这些仓库级别信息的全面理解至关重要,因为它允许他们在相应的开发环境中准确编写代码,避免任何误解或错误——这在编程上下文中常被称为“幻觉”。其次,程序员应该逐渐熟悉仓库。通过借鉴仓库内类似模块的灵感,他们可以在为特定任务编写代码时模仿之前的设计和实现。

为了与人类编程的逻辑过程保持一致,我们提出了一种仓库级别的代码方案RepoFuse,利用仓库内其他文件的信息提高代码补全准确率。具体来说,我们引入两类上下文信息:Semantic Context和Similar Context,它们分别指示当前补全环境中可用的程序依赖语义信息和仓库中与之相关的相似代码片段。如图3所示,模型补全左上角的代码片段时,在Semantic Context(红色)和Similar Context(绿色)的指导下,可以正确的补全出答案。

图3:Semantic和Similar Context的示例

RepoFuse的工作流程如图4所示,分为三个阶段:Semantic Context Analysis、Similar Context Retrieval和Relevance-Guided Context Selection,下面的章节将分别进行详细介绍。

图4:RepoFuse工作流程

Semantic Context Analysis

在软件开发中,我们通常使用Import语句引入包、模块或头文件等内容,表明了当前文件可用的类及方法。如果缺少这些信息,模型在补全相关内容时只能靠猜测,从而产生幻觉问题,我们认为这些信息对当前文件的代码补全具有“理性”指导的意义。假设我们将代码补全的过程视作做数学题题的过程,那这些跨文件的依赖信息可以视作这道题背后的数据公式、数学定理等。具体来说,我们采用了一种专门的工具,称为Repo-specific Semantic Graph。这种图结构是对传统代码依赖图的扩展,用于分析和展示代码库中不同实体(如函数、类、模块等)之间的关系。它使用图数据结构来呈现这些实体及其相互之间的依赖关系,并以多重有向图的形式存储这些信息,它的基本结构信息如下:

  1. 图(Graph):由节点和边构成

  2. 节点(Node): 具体包括Module、Class、Function和Variable

  3. 边(Edge): 具体包括Constructs、Imports、BaseClassOf、Overrides、Calls、Instantiates、Uses

在这个设计中,Repo-specific Semantic Graph会使用Graph类来存储代码实体(Node对象)和它们之间的依赖关系(Edge对象)。每个节点都会记录其在代码库中的位置,以及它的类型和名称。每条边则标识了两个节点之间的关系类型,以及关系在代码中的位置。

举一个简单的例子,如果一个函数A调用了另一个函数B,则可以在Repo-specific Semantic Graph中创建两个Node对象来表示这两个函数,并创建一个Edge对象来表示Calls关系,并在这个Edge对象存储下调用点(Call site)的位置。同样道理,如果一个函数A实例化了一个类X,则可以在依赖图中创建两个Node对象来表示A和X,并创建一个Edge对象来表示Instantiates关系,并在这个Edge对象存储下发生A实例化X(Object instantiation statement)的位置信息。Repo-specific Semantic Graph将这些对象组织成一个多重有向图,使得可以高效地查询任何代码元素的依赖关系。

这里以TinyDB的代码仓库为例,构建的Repo-specific Semantic Graph可以表示成下面这样的图。这里把不同关系表示成不同的边的颜色,节点的大小根据节点的度(degree)而定。

图5:Repo-specific Semantic Graph示例

Similar Context Retrieval

在程序开发中,我们如果要续写代码,时常会参考与当前正在编辑的代码片段相似的代码。如图3所示,图中的 se1 和 se2 均与当前代码片段 ck∗ 中出现大量重复的token,如user和service。这很可能意味着它们实现了与当前代码块相似甚至相同的功能,对代码补全过程有较大的指导意义。

所以,根据当前编辑文件中未完成的代码块 ck∗ ,我们可以通过一系列技术(如文本检索,向量检索),在其他源文件中发现几个相似的代码块(我们称为Analogy Context),并引入代码补全过程中。

Relevance-Guided Context Selection

Semantic Context和Similar Context都提供了比较有价值的信息。然而,在现实场景中,代码补全对于时间性能非常敏感。如果我们直接拼接这两类上下文(Dual Context),会导致Prompt过长,从而在LLM推理阶段引入额外的时间开销。为了有效地利用这两种上下文,我们提出了一种基于相关性的上下文选择技术,称为Relevance-Guided Context Selection(RCS),旨在通过相关性指导选择对模型补全最有益的上下文,我们将RCS策略选择出来的Context称为Optimal Dual Context(ODC)。

定义一个相关性打分方式 rck∗ ,规定 rck∗(e) 表示上下文片段 ck∗ 与待补全代码片段 e 之间的某种相关程度。在实践过程中,我们首先使用 rck∗ 对集合 U 中的候选代码片段从高到低进行排序,然后依次选择代码片段,直至达到长度上限 L 为止。以图2中的情况为例,我们的RTG策略选择了 se1 , se2 , si1 来加入prompt中。然后RepoFuse生成的代码中就借鉴了 ec1 中的代码validate user(user.uid, user.token)。与此同时,方法validate user的方法头,以及变量uid和token在类UidTok中的定义,都包含在了Semantic context中。在RepoFuse框架的引导下,大模型不仅看到了相似的代码实现,而且倾向于生成语法语义正确的调用,因此能在仓库级别代码补全任务中得到了更好的效果。

具体来说,我们设置了以下4种相关性函数 rck∗ :

  • Oracle:在这个理想化的场景中,候选集合 U 中的每个代码片段 e 分别与待补全的代码片段 ck∗ 拼接成Prompt输入给语言模型,而生成代码与真实代码(Ground Truth)之间的编辑相似性指标被作为其得分。该方法本质上是使用后验的方式评估候选集合 U 中每个代码片段的相关性,但由于需要巨大的计算需求,无法在实际场景中应用。

  • Semantic Similarity:我们使用Embedding模型对每个上下文 e 以及未完成的代码块 ck∗ 的语义表示进行编码。这些Embedding的余弦相似度用作得分。具体来说,我们采用了Unixcoder和CodeBert作为Embedding模型。

  • Lexical Similarity:使用了Jaccard Similarity和Edit Similarity进行相似度打分。

  • Random:随机打分,作为Baseline。

实验结果

实验设置

数据集:我们使用了目前的Sota数据集CrossCodeEval。CrossCodeEval是一个全面的数据集,专为评估仓库级别的代码补全框架而设计。它包括Python、Java、TS和C#的代码片段,并专注于理解跨文件上下文以进行准确的代码预测。我们采用EM(Exact Match)和ES(Edit Similarity)作为评估指标,遵循CrossCodeEval提供的定义。

模型选择:为了避免数据泄露,我们选择了三个2023年中之前发布的,模型最大长度支持8k的模型:StarCoder、CodeLlama、DeepSeek-Coder三个模型。考虑到实际补全场景很少使用参数量过大的模型,我们的实验聚焦在大小处于1B和7B之间的模型。由于上述模型都支持Fill-In-The-Middle(FIM)方式补全,为了贴近真实场景,本文所有的实验均采用FIM方式进行推理。

Baseline选择:为了评估RepoFuse的整体性能,我们选择了三种开源的、基于检索增强的仓库级代码补全方法进行对比。由于RepoFuse不涉及任何模型二次预训练或微调流程,为了保证公平对比,我们排除掉一些需要引入模型训练的工作,如[2], [3], [9]。具体来说,我们对比的Baseline有:

  • RLPG[1]:RLPG使用Repo-Level Prompt Generator和Repo-Level Prompt Proposals生成特定于示例的提示。在我们的实现中,我们直接利用RLPG生成的提示,尽可能多地将上下文输入到大语言模型中。这种方法仅支持Java语言。

  • RG-1和RepoCoder[4]:这种方法使用固定的Chunk size将代码仓库分割成代码块,并基于文本相似度检索相关上下文。然后,它迭代执行检索-生成循环,使用前一次生成的结果去检索下一次生成的上下文。RG-1代表循环中的第一次检索和生成步骤,而RepoCoder代表标准的迭代过程。在我们的实现中,迭代次数设为2。RG-1和RepoCoder都支持Java和Python语言。

  • CCFinder[7]:这是一个跨文件上下文查找工具,它通过Import语句从预构建的Project Context Graph中检索相关的跨文件上下文。我们使用了CCFinder-k(k = 2),将待补全代码实体的2跳邻居作为上下文。CCFinder仅支持Python语言。

补全性能

图6展示了RepoFuse与其他Baseline方法在CCeval数据集上Python和Java子集上的效果,其中方法名称后面的数字表示允许的上下文最大长度。如图6所示,结果表明RepoFuse在性能上表现卓越。具体而言,在Python数据集中,RepoFuse在EM指标提高了3.964%,ID-F1分数提升了3.786%。在Java数据集中,EM提高了3.014%,ID-F1分数提升了2%。值得注意的是,即使在1024的上下文长度下,RepoFuse的表现仍然超过了所有使用4096 上下文长度的Baseline方法。这凸显了RCS策略的重要性,即使在严格的输入限制下,也能提高代码补全的准确性。

图6:RepoFuse与Baseline方法在Cceval数据集上的结果

此外,我们还评估了多个模型使用不同类型Context时,在各种Context长度(从256到4096)下的性能表现。结果如图7所示,在绝大部分实验设置下,使用RCS策略得到的ODC(Optimal Dual Context)的效果均优于单独使用SE(Semantic Context)或SI(Similar Context),说明两种类型的数据之间存在互补性。值得注意的是:ODC在1024长度的表现超过了SE和SI在4096长度下的表现。这说明了在有限的Token长度下,利用ODC的重要性:不仅提高了性能,还提高了推理速度。此外,DeepSeek-Coder模型在与其大小相当的其他语言模型中表现突出,这意味着在预训练期间整合跨文件数据显著提高了仓库级代码补全任务的性能。

图6:不同Context设置在多个模型上的性能比较

推理效率

RCS带来的推理性能提升:尽管在使用ODC + 4096 Context长度的配置能达到最好的效果,但它会显著降低推理速度。为了更好地适应需要快速响应的环境,我们使用StarCoder-1B模型上评估了使用不同Context设置在推理效率和性能上的表现。如图7所示,ODC(ODC_1024)不仅在EM性能上保持优于SI和SE,还提高了推理速度并降低了延迟。雷达图表明,RepoFuse(ODC_1024)相比SE实现了13.89%的吞吐量增加,并将延迟降低了33.3%。由于在CrossCodeEval Python数据集上检索到的SI上下文数量有限,SI的实际令牌长度与ODC_1024的长度相近,因此它们的吞吐量和延迟性能接近,而ODC_1024比SI提高了15.9%的EM。因此,ODC_1024这种配置证明RepoFuse有效地平衡了高准确率和优化的推理速度。

图7:不同Context设置在StarCoder-1B上的推理效率与性能

不同相关度函数的比较

本节我们评估在使用Semantic & Similar两类上下文信息时(Dual Context),RCS策略中不同相关度函数的效果,具体如图8所示。从图中可以看到,在上下文长度较小(256、512)时,Oracle效果明显优于其他相关函数。随着上下文长度增长,各策略间没有显著的性能差异。这证明了在有限的Token长度 L 下,相关性分数函数对补全效果的重要性。在Oracle之外的策略中,基于UniXcoder的相似度分数表现最佳,而随机策略的效果最差,这与RepoBench的见解相印证。Jacarrd Similarity的效果略低于UniXcoder,但却有显著的计算性能优势,可以考虑应用在实际补全场景中。同样的结论在单独使用Semantic或Similar上下文时也可以观察到,由于篇幅限制此处不过多赘述。

图8:RCS不同相关度函数的效果

未来工作展望

本文介绍了一种新颖的仓库级别代码补全技术RepoFuse,通过引入两类不同视角的上下文信息辅助模型进行补全,显著提升了补全的效果。并且提出基于相关性指导的上下文选择技术,在保证效果的前提下限制Prompt长度,提升推理效率。目前,我们已经将相关技术应用到CodeFuse插件中。在未来,RepoFuse会继续在以下方向进行探索:1. 更轻量的程序分析技术,有助于提升准确性和效率;2. 更精细的上下文选择策略设计:例如更细的上下文选择粒度和更好的相关性度量分数。

此处仅列出关键参考文献,详细参考文献请查看原论文

[1]. RLPG:Repository-Level Prompt Generation for Large Language Models of Code

[2]. RepoFusion: Training Code Models to Understand Your Repository

[3]. ReACC: A Retrieval-Augmented Code Completion Framework

[4]. RepoCoder: Repository-Level Code Completion Through Iterative Retrieval and Generation

[5]. CROSSCODEEVAL: A Diverse and Multilingual Benchmark for Cross-File Code Completion

[6]. RepoBench: Benchmarking Repository-Level Code Auto-Completion Systems

[7]. COCOMIC: Code Completion By Jointly Modeling In-file and Cross-file Context

[8]. CodePlan: Repository-level Coding using LLMs and Planning

[9]. Repoformer: Selective Retrieval for Repository-Level Code Completion

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

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

相关文章

性能测试趋势 2024

效率。其主要目标是确保软件满足性能要求并提供令人满意的用户体验。 有效的性能测试需要仔细的规划、真实的场景以及使用适当的工具来模拟真实世界的条件。定期进行性能测试有助于确保软件系统能够处理不同的工作负载并提供积极的用户体验。性能测试的未来正在受到技术发展的…

SSL证书配置

SSL证书配置 证书申请nginx 配置ssl证书 今天群友发现我的博客证书过期了,重新申请一个免费的部署一下 证书申请 点击创建证书 绑定对应的域名,选择快捷签发,点击提交审核 点击验证,如果购买的域名和服务器都在同一个账号下&…

WPF学习(7)- Control基类+ContentControl类(内容控件)+ButtonBase基类

前面给大家介绍完了WPF所有的布局控件,属性以及使用案例,从这里咱们就开始学下内容控件。 Control基类 Control是许多控件的基类。比如最常见的按钮(Button)、单选(RadioButton)、复选(CheckBox)、文本框…

AIGC大模型实践总结(非常详细)零基础入门到精通,收藏这一篇就够了

大模型浪潮席卷全球,在各行各业中的重要性愈发凸显,呈现出一股不可逆转的发展趋势。这一年本人所在业产技也在这一过程中持续探索和尝试AIGC。本文一方面是对AIGC实践的总结回顾,同时也是本人学习实践AIGC过程中一些笔记、心得分享。因个人能…

Linux云计算 |【第二阶段】CLUSTER-DAY4

主要内容: 块存储应用案例(快照、快照回滚、快照克隆)、分布式文件系统(文件系统的构成:inode和block,创建存储池实现inode和block)、对象存储(radosgw) 补充&#xff1…

C++ STL与string类

一 什么是STL? STL,全称是标准模板库(Standard Template Library),是C标准库的一部分。STL提供了一些常用的数据结构和算法,帮助开发者更方便、高效地编写代码。通过使用STL,开发者不需要重复造…

吴恩达机器学习笔记 三十九 协同过滤的TensorFlow实现

TensorFlow的一个优点:可以自动算出成本函数的导数 如上图,设 f( x ) wx,成本 J 为(wx - 1)^2,用GradientTape()这个函数,TensorFlow会记录计算成本J所需的操作序列,保存在 tape 中。 dJdw为自动计算出的导…

图片转文字怎么操作?教你几招图片转文字小妙招

在日常的工作学习中,我们每天可能会接触到大量的图片资料,无论是会议纪要、书籍扫描页、还是网络上的有用信息截图,如果能快速将这些图片中的文字提取出来,无疑将极大提升我们的工作效率。下面给大家分享几种能够将图片转换成文字…

AI学习记录 - 自注意力机制的计算流程图

过段时间解释一下,为啥这样子计算,研究这个自注意力花了不少时间,网上很多讲概念,但是没有具体的流程图和计算方式总结…

多线程 01:Java 多线程学习导航,线程简介,线程相关概念的整理

一、概述 记录时间 [20240807] 立秋 & 128 创作纪念日 本文是关于 Java 多线程学习的导航篇,总览了有关多线程学习的几个模块。简单介绍了一些与线程相关的基本概念,便于后续展开多线程的学习。 前置知识:Java 基础篇;Java 面…

腾讯云AI代码助手的实用性能以及带给开发者的便捷开发陪伴

腾讯云AI代码助手的实用性能以及带给开发者的便捷开发陪伴 前言一、开发环境介绍二、腾讯云AI代码助手使用实例1 一键代码补全2 与腾讯云ai代码助手对话3 直接对源码进行注释,查错 三 获得的帮助与提升四 对腾讯云AI代码助手的建议总结 前言 在日常的编程工作的生活…

SQL报错注入之updatexml

目录 1.updatexml报错原理 2.判断是否有注入点 我们在地址栏中输入?id1 我们在地址栏中输入?id1-- 3.updatexml报错注入 3.1爆库名 3.2爆表名 3.3爆字段名 3.4爆数据 1.updatexml报错原理 updatexml(xml_doument,XPath_string,new_value) 第一个参数:XML…

07-软件参数的基本配置

1.设置交叉 2.Design insight 关闭 3.数据保存设置 4.原理图设置 5.PCB-General设置 PCB-Board Insight Modes设置 PCB-Board Insight Color Overrides PCB-DRC Violations Display PCB-Interactive Routing PCB-Defaults

【C++】C++11的新特性 — 线程库 ,原子操作 , 条件变量

勇敢就是接受发生在你身上的事,并把它尽力做到最好。 -- 约翰・欧文 -- C11的新特性 1 线程1.1 线程概念1.2 C中的线程1.3 线程并行1.4 锁 2 原子操作3 条件变量Thanks♪(・ω・)ノ谢谢阅读!!!下…

最短路问题中的bellman-ford算法

最短路问题中的bellman-ford算法 题目 如果要处理单源最短路问题当中存在负权边的,那么就需要用到 bellman-ford算法和SPFA算法,一般情况下都是用 SPFA算法,除了有边数限制的情况只能用bellman-ford算法,比如下面这种 题目 给定…

SVG入门指南

前言 SVG 是一种使用 XML 描述 2D 图形的语言&#xff0c;与传统前端 DOM 开发比较类似&#xff0c;本文尝试总结一下 SVG 的基本用法。 基本图形绘制 与 canvas 不同&#xff0c;svg 使用声明式的方式来绘制图形&#xff0c;比如绘制一个矩形&#xff1a; <svg width&q…

Elastic 利用由 Search AI 提供支持的自动导入功能加速 SIEM 数据导入

作者&#xff1a;来自 Elastic Jamie Hynds, Mark Settle Elastic 正在通过自动导入功能自动完成 SIEM 数据导入&#xff0c;从而加速采用 AI 驱动的安全分析。这项新功能&#xff08;安全分析或 SIEM 解决方案中独一无二的功能&#xff09;可自动开发自定义数据集成。Elastic …

轻松上手MYSQL:掌握MYSQL聚合函数,数据分析不再难

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索MYSQL聚合函数之旅✨ &#x1f44b; 大家好&#xff01;文本学习和探…

240807-Gradio客户端GUI与服务端API分离代码示例

A. 客户端服务端分离的最终效果 B. 前后端核心代码 Gradio支持将前端界面&#xff08;客户端&#xff09;与后端逻辑&#xff08;服务端&#xff09;分离。通过这种方式&#xff0c;客户端负责用户交互和显示&#xff0c;而服务端负责实际的数据处理和功能实现。 以下是如何实…

买Zoho企业邮箱赠公司后缀的域名吗?

随着市场上企业邮箱服务提供商的增多&#xff0c;选择适合自身需求的服务变得尤为重要。其中一个常见的问题是&#xff1a;购买Zoho企业邮箱服务时是否会赠送公司后缀的域名&#xff1f;赠送域名有哪些套路&#xff1f;本文将详细探讨这些问题。 一、买Zoho企业邮箱赠送公司后…