Prompt 策略:代码库 AI 助手的语义化搜索设计

news2024/12/23 17:27:34

在过去的一周里,为了更好的构建 AI Agent 框架 Chocolate Factory(以下简称 CF),我们加入了一个新的应用:代码库 AI 助手。

在设计时,为了更好的在框架底层提供这种能力,我们参阅了 Bloop 应用、LangChain、Spring AI、LlamaIndex 框架等的代码与思想,参考/复制(基于 Apache 2.0 协议) LangChain4j 的一部分 VectorStore 实现。

详细见代码库:https://github.com/unit-mesh/chocolate-factory

详细文档见:https://framework.unitmesh.cc/

Demo 视频见:

引子:代码库 AI 助手

首先,先让 ChatGPT 根据我们的素材总结了一下:什么是代码库 AI 助手?负责读取和格式化数据,以便将其分成适合存储在数据库中的片段。

代码库 AI 助手是一种智能工具,通常使用自然语言处理和机器学习技术,旨在帮助开发者更有效地管理和理解大型代码库。这些助手能够回答关于代码库的问题、提供文档、搜索代码、识别错误源头、减少代码重复等,从而提高开发效率、降低错误率,并减轻开发者的工作负担。

其设计目标是使开发者能够以更直观和自然的方式与代码库进行互动,减少繁琐的文档查找和编码任务,从而加速软件开发过程。

简单来说,用户直接提出问题,基于现有的业务逻辑实现,去进去后续的任务,如:需求是如何实现的?根据 bug 来分析与代码的关系,并提供修复意见。

先让我们看个示例:

代码库 AI 助手问答示例

问题:Semantic Workflow 是如何实现的?

ChatGPT 根据 CF 检查的代码,返回的答案:

根据提供的代码,我们可以看到 CodeSemanticWorkflow 是一个继承自 Workflow 的类,它实现了 execute 方法来执行语义化的代码搜索。

在 execute 方法中,它首先创建了一个 ElasticsearchStore 对象,并获取了用户最后一条消息的内容作为问题。然后,它使用 SemanticProblemAnalyzer 对象来分析问题,该对象使用 llmProvider 来完成问题的解析。接下来,它使用 SemanticSolutionExecutor 对象来执行语义化的代码搜索,并将结果转换为 Flowable。最后,它调用 toFlowableResult 方法将结果转换为 Flowable 并返回。

下面是一个使用 PlantUML 绘制的流程图,展示了 CodeSemanticWorkflow 的执行过程:

@startuml
start
:创建 ElasticsearchStore对象;
:获取用户最后一条消息的内容;
:使用 SemanticProblemAnalyzer对象分析问题;
:使用 SemanticSolutionExecutor对象执行语义化的代码搜索;
:将结果转换为 Flowable<Answer>;
:将结果转换为 Flowable<WorkflowResult>;
stop
@enduml

希望以上信息能够回答您的问题。

CF 代码库 AI 助手设计

在设计 Chocolate Factory(以下简称 CF)时,我们依旧采用的是 DDD 思想所构建的。

第一部分,围绕于问题空间的求解,对用户问题进行分析与转换,以获得潜在的解决方案。

第二部分,围绕于解决空间的实现,即通过检索增强(RAG,Retrieval Augmented Generation),来获得对应问题的答案。

为此,在第一部分,我们将会分析问答的问题,以构建出一个针对于解决方案的 DSL。然后,围绕于 DSL 来进行检索,获得相应的答案,最后交由 LLM 来进行总结。

Prompt 构建策略阶段 1:问题求解

在设计上,为了更好的进进行检索,在设计 CoUnit 时,我们拆分成三种检查条件:

  • englishQuery,将中文翻译成英文,再结合英文进行搜索。

  • originLanguageQuery,如我们在使用中文里,翻译成英语可能不标准,但是注释中则可能是使用中文存在,所以相似式也会很靠谱。

  • hypotheticalDocument,假设性文档,即根据用户的请求生成代码,再结合生成的代码进行相似式搜索。

所以,在阶段一就需要由 LLM 来分析用户的问题,并给出如上的三个检查条件。hypotheticalDocument 参考的是 Bloop 的设计:

  • hypotheticalDocument is a code snippet that could hypothetically be returned by a code search engine as the answer.

  • hypotheticalDocument code snippet should be between 5 and 10 lines long

不过,由于一次给了三个条件,偶尔还是存在概率性的假设性文档出错的问题。

Prompt 构建策略阶段 2:检索增强

在现有的设计里,一个代码库 AI 助手本质也是 RAG(检索增强,Retrieval Augmented Generation),因此可以分为 indexing 阶段和 querying 阶段。

代码库 AI 助手:indexing 阶段

d8571b8774e6c43852998339edb83792.png

在 indexing 阶段,基本上就是:

  • 文本分割(TextSplitter)。负责将源数据分割成较小单元(Chunks)的工具或组件。

  • 文本向量化(Vectoring)。负责将拆分好的 Chunk 转变化向量化数组。

  • 数据库(Vector Database)负责通过高效的向量检索技术来实现文档片段的快速检索。

在文本向量化上,我们使用的是 SentenceTransformer 的本地化极小 NLP 模型(22M 左右)。对于代码来说,它是结构化的形式,并且也经过了 GitHub Copilot、Bloop 的充分验证,所以准确度并不差。

由于使用的是本地化模型,通过 CPU 就可以快速计算完成,所以更新策略上可以和 CI、CD 集成。一旦有代码更新时,就可以 indexing。

代码库 AI 助手:querying 阶段

e065f4a27279032752044d0663aaf736.png

在 querying 阶段,我们会围绕阶段 1 的 DSL,先转换 DSL 的文本成对应的向量化形式。

再对其进行对应的内容检索:

// 基于英语的相关代码列表
val list = store.findRelevant(query, 15, 0.6)
// 基于中文的相关代码列表
val originLangList = store.findRelevant(originQuery, 15, 0.6)
// 相关的假设性代码列表
val hydeDocs = store.findRelevant(hypotheticalDocument, 15, 0.6)

随后,再对结果进行排序。考虑到诸如 《Lost in the Middle: How Language Models Use Long Contexts》对于长文本的影响,我们在 CF 中也引入了对应的方式,因此一个排序后的代码结果如下所示:

0.7847863// canonicalName: cc.unitmesh.cf.domains.semantic.CodeSemanticWorkflowTest
0.76635444// canonicalName: cc.unitmesh.cf.domains.semantic.CodeSemanticDecl
0.74648994// canonicalName: cc.unitmesh.cf.core.flow.ProblemAnalyzer
0.7410852// canonicalName: cc.unitmesh.cf.domains.spec.SpecDomainDecl
0.72767156// canonicalName: cc.unitmesh.cf.core.flow.DomainDeclaration
0.73245597// canonicalName: cc.unitmesh.cf.core.flow.model.WorkflowResult
0.7434818// canonicalName: cc.unitmesh.cf.domains.interpreter.CodeInterpreterWorkflow.execute
0.757218// canonicalName: cc.unitmesh.cf.core.flow.Workflow
0.7722022// canonicalName: cc.unitmesh.cf.domains.semantic.flow.SemanticProblemAnalyzer
0.807935// canonicalName: cc.unitmesh.cf.domains.semantic.CodeSemanticWorkflow.execute

前面的数字便是相关性的 score,后面的 canonicalName 则是相关代码的信息,可能是类、类方法、方法等。

Prompt 策略 3:代码拆分策略

在代码的分割上,不同的框架有不同的策略,LangChain 是基于关键字的方式,LlamaIndex 是基于 TreeSitter 方式,Bloop 则是基于 TreeSitter 的 S-表达式创建。

我们则是采用 ArchGuard Scanner 的标准化代码结构方式,除了可以直接利用 ArchGuard 项目的现有的 CLI 基础设施,在形式上与结果上也更加准确。诸如于可以针对于 Interface、abstract class 等进行优化 Chunk 的拆分规则,并构建出 canonicalName 的方式,来方便索引和定位。

代码拆分规则

我们参考的折分规则是:https://docs.sweep.dev/blogs/chunking-2m-files 。即:

  1. 代码的平均 Token 到字符比例约为1:5(300 个 Token),而嵌入模型的 Token 上限为 512 个。

  2. 1500 个字符大约对应于 40 行,大致相当于一个小到中等大小的函数或类。

  3. 挑战在于尽可能接近 1500 个字符,同时确保分块在语义上相似且相关上下文连接在一起。

对应的模型如下:

classCodeSplitter(
private val comment: String= "//",
private val chunkLines: Int= 40,
private val maxChars: Int= 1500,
// TODO: for unsupported languages, we can use the following heuristic to split the code
    val chunkLinesOverlap: Int= 15,
)

当然了,这里的 chunkLinesOverlap 是还没有襰的。

Chunk 拆分实现

由 CF 的代码库 AI 助手生成:

问题:CodeSplitter 是如何实现的

答案:

根据提供的代码,CodeSplitter 是一个用于将代码拆分成多个文档的类。它有一个 split 函数,该函数接受一个 CodeDataStruct 对象并返回一个 Document 对象的列表。

在 split 函数中,它首先根据代码的长度判断是否需要拆分。如果代码的长度小于等于 maxChars(默认为1500个字符),则直接将整个代码作为一个文档返回。

如果代码的长度大于 maxChars,则会遍历 CodeDataStruct 对象中的每个函数,并将函数的内容拆分成多个文档。拆分的方式是根据 chunkLines(默认为40行)将函数内容分割成多个部分。如果函数的行数超过了 chunkLines,则只取前 chunkLines 行作为一个文档的内容。

拆分后的文档的内容由 canonicalName 和函数的内容组成。如果拆分后的内容长度超过了 maxChars,则会截取前 maxChars 个字符作为文档的内容。

小结

本文深入探讨了代码库AI助手的设计和实现策略,包括问题求解、检索增强和代码拆分。这些策略有助于提高开发者与代码库的互动效率和准确性,加速软件开发过程。

详细见代码库:https://github.com/unit-mesh/chocolate-factory 。

详细文档见:https://framework.unitmesh.cc/ 

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

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

相关文章

科研小工具|慢性阻塞性肺疾病全球创议

简介 慢性阻塞性肺疾病全球创议&#xff08;the Global Initiative for Chornic Obstructive Lung Disease&#xff0c;GOLD&#xff09;是慢性阻塞性肺疾病&#xff08;COPD&#xff09;诊断、治疗与预防在全球范围内的标准。颁布GOLD的目的在于&#xff0c;增加医疗卫生工作…

pdd24版滑块

最近pdd改版了&#xff0c;在原来的基础之上加了一个content字段&#xff0c;然后pdd滑块分为两个大类。 一个是22类型的&#xff0c;在之前的文章里面有介绍&#xff0c;感兴趣也可以去看看。 详情的滑块跟普通的版本不同&#xff0c;但是有的算法也沿用了之前22版的东西&a…

【Seata】05 - Seata Saga 模式简单整理、Docker 部署 Nacos 单机(基于 Jpom)相关配置

文章目录 前言参考目录Saga 模式知识点简单整理1、适用场景、优缺点2、Saga 模式的使用3、可能出现的问题以及解决方法 Docker 部署 Nacos 单机&#xff08;基于 Jpom&#xff09;步骤 1&#xff1a;拉取镜像步骤 2&#xff1a;构建容器步骤 3&#xff1a;Nacos 设置 Seata 配置…

安装Python第三方库

视频版教程 Python3零基础7天入门实战视频教程 在Python的标准安装中&#xff0c;包含了一组自带的模块&#xff0c;这些模块被成为“标准库”。比如常用的math,random,datetime,os,json等等。 此外&#xff0c;还有很多的第三方模块&#xff0c;或者叫做库也行&#xff0c;叫…

TienChin 渠道管理-配置校验失败信息

新建 ValidationMessages.properties&#xff1a; channel.name.notnull渠道名称不能为空 channel.type.notnull渠道类型不能为空 channel.status.notnull渠道状态不能为空 channel.type.invalid渠道类型无效 channel.status.invalid渠道状态无效

linux上安装redis

这篇文章简单地介绍一下怎么在linux虚拟机上完成redis的安装。 首先&#xff0c;访问Redis官网&#xff0c;点击首页的【Get Started】&#xff0c;然后点击Install Redis on Linux 然后按照页面内容提示&#xff0c;在Ubuntu上安装redis 只需要在终端依次输入以下命令&#xf…

面试官:Vue实例挂载的过程中发生了什么?

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 一、思考 一、分析 三、结论 一、思考 我们都听过知其然知其所以然这句话 那么不知道大家是否思考过new Vue()这…

权限提升WIN篇(腾讯云,CS,MSF)

溢出漏洞 信息收集 操作系统版本ver&#xff0c;systeminfo漏洞补丁信息systeminfo操作系统位数systeminfo杀软防护tasklist /svc网络netstat -ano,ipconfig当前权限whoami 筛选EXP 根据前面的信息收集中的系统版本&#xff0c;位数和补丁情况筛选出合适的EXP 提权 根据EX…

JVM——4.垃圾回收

这篇文章我没来讲一下JVM中的垃圾回收。这是比较重要&#xff0c;内容也比较多的一篇文章。 目录 1.垃圾回收概述 2.如何判断对象可以回收 2.1引用计数法 2.2可达性分析算法 2.2.1GCRoot的选取 2.3再谈引用 2.3.1强引用 2.3.2软引用 2.3.3弱引用 2.3.4虚引用 2.3.5…

2023关于赴日IT培训你需要了解的

有人还是好奇日本IT行业真的那么缺人吗&#xff1f;我告诉你&#xff1a;缺&#xff01;和中美完全不同的是&#xff0c;日本的IT行业面临着非常严重的程序员缺口。根据日本经济产业省进行的“关于IT人才供需的调查”&#xff0c;预计到2030年&#xff0c;日本IT行业将会有45万…

进程的就绪、执行、阻塞和挂起

假设我们有一个进程, 它需要的资源有CPU, 资源A(在进程创建时为其分配), 资源B(进程运行时才发现需要资源B), 现在用这个进程来分析一下进程的几种状态. 先看图: 图1: 进程的几种状态 1. 创建 --> 就绪(资源A): 操作系统为进程分配资源A, 进程进入就绪态, 等待CPU. 进程当…

ICS TRIPLEX T8310 自动化控制模块

ICS TRIPLEX T8310 是一种自动化控制模块&#xff0c;通常用于工业控制和自动化系统中&#xff0c;以实现对各种过程和设备的自动控制。以下是可能包括在 ICS TRIPLEX T8310 自动化控制模块中的一些常见产品功能&#xff1a; PLC&#xff08;可编程逻辑控制器&#xff09;功能&…

树结构构建,字典树快速生成。

表结构 查出list后&#xff0c;用工具类转换。工具类代码如下&#xff1a; 下面展示一些 内联代码片。 public static List<JSONObject> toTreeList(List tList, String oidkey, Stripspidkey) List<JSONObject> jsonObjectList JSONArray. parseArray (JSON.…

公司电脑监控软件哪个好?(常用公司电脑监控软件有哪些?)

随着科技的发展&#xff0c;公司对员工电脑的监控已经成为了企业管理的重要手段。然而&#xff0c;如何选择合适的公司电脑监控软件&#xff0c;以及如何避免员工发现&#xff0c;成为了企业管理者需要面对的问题。 一、公司电脑监控软件哪个好&#xff1f; 针对公司电脑监控软…

Hive工作原理

Hive 工作原理详解-阿里云开发者社区 Hive的服务端组件 1. Driver组件&#xff1a;该组件包括&#xff1a;Compiler、Optimizer、Executor,它可以将Hive的编译、解析、优化转化为MapReduce任务提交给Hadoop1中的JobTracker或者是Hadoop2中的SourceManager来进行实际的执行相应…

《数字图像处理-OpenCV/Python》连载(7)视频文件的读取与保存

《数字图像处理-OpenCV/Python》连载&#xff08;7&#xff09;视频文件的读取与保存 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第1章 图像的基本操作 为…

记录一下 ThinkPHP 使用JWT进行身份验证

ThinkPHP使用JWT身份验证 1.composer安装jwt&#xff0c;安装命令&#xff1a;composer require firebase/php-jwt 安装成功后会在vendor目录下生成firebase目录文件 第二步&#xff1a;生成token 先引入jwt use Firebase\JWT\JWT; public function getToken($user){//使…

安达发|APS软件多工厂架构引领生产管理新革命

APS多工厂架构是一种生产管理系统&#xff0c;它通过将多个工厂的生产过程进行整合和优化&#xff0c;实现了生产效率的提高和成本的降低。在APS多工厂架构中&#xff0c;每个工厂都有自己的生产线和生产计划&#xff0c;但是它们之间可以进行协调和协作&#xff0c;以确保整个…

深度学习归一化原理及代码实现(BatchNorm2d,LayerNorm,InstanceNorm,GroupNorm)

文章目录 概述形式原理理解源代码实现1.BatchNorm2d2.LayerNorm3.InstanceNorm4.GroupNorm 概述 本文记录总结pytorch中四种归一化方式的原理以及实现方式。方便后续理解和使用。 本文原理理解参考自 https://zhuanlan.zhihu.com/p/395855181 形式 四种归一化的公式都是相同的…

油猴Safari浏览器辅助插件:Tampermonkey for Mac中文版

油猴脚本Tampermonkey是一款油猴Safari浏览器辅助插件&#xff0c;是一款适用于Safari用户的脚本管理&#xff0c;能够方便管理不同的脚本。虽然有些受支持的浏览器拥有原生的用户脚本支持&#xff0c;但tampermonkey油猴插件将在您的用户脚本管理方面提供更多的便利&#xff0…