上下文工程:基于 Github Copilot 的实时能力分析与思考

news2024/12/23 17:22:41

上个月在计划为 AutoDev 添加多语言支持时候,发现 GitHub Copilot 的插件功能是语言无关的(通过 plugin.xml 分析),便想研究一下它是如何使用 TreeSitter 的。可惜的是,直到最近才有空,研究一下它是如何实现的。探索的过程中,发现:Copilot 围绕上下文做了非常之多的工作,便想着写一篇文章总结一下。

GitHub Copilot 的上下文构建

与 ChatGPT 相比,GitHub Copilot 的强大之处在于,它构建了足够多的上下文,结合其对 LLM 的训练(或微调),可以写出非常精准的生产级代码

Copilot 的可见上下文

在肉眼可见的级别里,即我们自身的使用感受,我们可以发现 Copilot 不仅是读取当前文件的源码,而是一系列相关文件的源码,以构建更详细的上下文。

03b191fd351a48a989fba181f5b7d3de.png

简单可以先划分三个场景:

  • 当前文件。可以感知某个类的属性和方法,并做出自动填充。

  • 相近文件。如测试文件,可以知道被测类的信息,并自动编写用例。

  • 编辑历史(疑似)。即当我们以某种方式修改多个代码时,它也能识别出这个变化。

而在未来,相信它会获取诸如项目上下文等信息,如 Gradle 依赖、NPM 依赖等信息,避免在打开的 tab 不够用的情况下,引用不存在的依赖。

而针对于企业自身的 AI 编程工具而言,还可以结合服务上下文、业务上下文进行优化。

Copilot 的不可见过程

结合网上的逆向工程资料,以及自己对代码的 debug 尝试,最后梳理了一个大致的 “四不像” (实在是懒得继续画)架构图:

2417fbeff8242e59451a87a227353bf9.png

其作用如下:

  • 监听用户操作(IDE API )。监听用户的 Run Action、快捷键、UI 操作、输入等,以及最近的文档操作历史。

  • IDE 胶水层(Plugin)。作为 IDE 与底层 Agent 的胶水层,处理输入和输出。

  • 上下文构建(Agent)。JSON RPC Server,处理 IDE 的各种变化,对源码进行分析,封装为 “prompt” (疑似) 并发送给服务器。

  • 服务端(Server)。处理 prompt 请求,并交给 LLM 服务端处理。

而在整个过程中,最复杂的是在 Agent 部分,从上下文中构建出 prompt。

Copilot 的 Prompt 与上下文

在 “公开” 的 Copilot-Explorer 项目的研究资料里,可以看到 Prompt 是如何构建出来的。如下是发送到的 prompt 请求:

{
  "prefix": "# Path: codeviz\\app.py\n#....",
  "suffix": "if __name__ == '__main__':\r\n    app.run(debug=True)",
  "isFimEnabled": true,
  "promptElementRanges": [
    { "kind": "PathMarker", "start": 0, "end": 23 },
    { "kind": "SimilarFile", "start": 23, "end": 2219 },
    { "kind": "BeforeCursor", "start": 2219, "end": 3142 }
  ]
}

其中:

  • 用于构建 prompt 的 prefix 部分,是由 promptElements 构建了,其中包含了: BeforeCursorAfterCursorSimilarFileImportedFileLanguageMarkerPathMarkerRetrievalSnippet 等类型。从几种 PromptElementKind 的名称,我们也可以看出其真正的含义。

  • 用于构建 prompt 的 suffix 部分,则是由光标所在的部分决定的,根据 tokens 的上限(2048 )去计算还有多少位置放下。而这里的 Token 计算则是真正的 LLM 的 token 计算,在 Copilot 里是通过 Cushman002 计算的,诸如于中文的字符的 token 长度是不一样的,如: { context: "console.log('你好,世界')", lineCount: 1, tokenLength: 30 } ,其中 context 中的内容的 length 为 20,但是 tokenLength 是 30,中文字符共 5 个(包含  )的长度,单个字符占的 token 就是 3。

到这里,我算是解决我感兴趣的部分,Agent 包里的 TreeSitter 则用于分析源码,生成 RetrievalSnippet ,其中支持语言是 Agent 自带的 .wasm 相关的包,诸如:Go、JavaScript、Python、Ruby、TypeScript 语言。

LLM 的上下文工程

上下文工程是一种让 LLM 更好地解决特定问题的方法。它的核心思想是,通过给 LLM 提供一些有关问题的背景信息,比如指令、示例等,来激发它生成我们需要的答案或内容。上下文工程是一种与 LLM 有效沟通的技巧,它可以让 LLM 更准确地把握我们的目的,并且提升它的输出水平。

简而言之,上下文工程是如何在有限的 token 空间内,传递最相关的上下文信息

所以,我们就需要定义什么是该场景下的,最相关的上下文信息

基于场景与旅程的上下文设计

它的基本思想是,通过分析用户在不同场景下的操作和行为,来获取与当前任务相关的上下文信息,从而指导 LLM 生成最佳的代码提示。

Copilot 分析了用户在不同场景下的操作和行为,如何使用 IDE 的旅程,以及与当前任务相关的指令和例子等信息,从而获取最相关的上下文信息。这些上下文信息可以帮助 LLM 更好地理解用户的意图,并生成更准确、更有用的代码提示。

例如,在用户编写 JavaScript 代码时,Copilot会分析用户在编辑器中的光标位置、当前文件的内容、变量、函数等信息,以及用户的输入历史和使用习惯等上下文信息,来生成最相关的代码提示。这些代码提示不仅能够提高用户的编码效率,还能够帮助用户避免常见的编程错误。

就地矢量化(Vector)与相似度匹配

“众知周知”,在 LLM 领域非常火的一个工具是 LangChain,它的处理过程类似于 langchain-ChatGLM 总结的:

69673590ef471b60131fafc75d4c6951.png

加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 -> 在文本向量中匹配出与问句向量最相似的 top k个 -> 匹配出的文本作为上下文和问题一起添加到 prompt中 -> 提交给 LLM生成回答。

为了处理大规模的自然语言处理任务,Copilot 在客户端使用了 Cushman + ONNX 模型处理。具体来说,Copilot 将 Cushman 模型的输出转换为向量表示,然后使用向量相似度计算来匹配最相关的本地文件。

除了就地矢量化(Vector)与相似度匹配,Copilot 还使用了本地的相似计算与 token 处理来管理 token,以便更好地处理大规模自然语言处理任务。

有限上下文信息的 Token 分配

而由于 LLM 的处理能力受到 token 数的限制,如何在有限的 token 范围内提供最相关的上下文信息,便是另外一个重要的问题。

诸如于如上所述的 Copilot 本地 prompt 分为了 prefix 和 suffix 两部分,在 suffix 部分需要配置 suffixPercent,其用于指定在生成代码提示时要用多少 prompt tokens 来构建后缀,默认值似乎是 15%。

通过增加 suffixPercent,可以让 Copilot 更关注当前正在编写的代码片段的上下文信息,从而生成更相关的代码提示。而通过调整 fimSuffixLengthThreshold,可以控制 Fill-in-middle 的使用频率,从而更好地控制生成的代码提示的准确性。

Copilot 如何构建及时的 Token 响应

为了提供更好的编程体验,代码自动补全工具需要能够快速响应用户的输入,并提供准确的建议。在 Copilot 中,构建了一个能够在极短时间内生成有用的代码提示的系统。

取消请求机制

为了及时响应用户的输入,IDE 需要向 Copilot 的后端服务发送大量的请求。然而,由于用户的输入速度很快,很可能会出现多个请求同时发送的情况。在这种情况下,如果不采取措施,后端服务会面临很大的压力,导致响应变慢甚至崩溃。

为了避免这种情况,可以采用取消请求机制。具体来说,在 IDE 端 Copliot 使用 CancellableAsyncPromise 来及时取消请求,在 Agent 端结合 HelixFetcher 配置 abort 策略。这样,当用户删除或修改输入时,之前发送的请求就会被及时取消,减轻后端服务的负担。

多级缓存系统

为了加速 Token 的响应速度,我们可以采用多级缓存系统。具体来说,在 IDE 端可以使用 简单的策略,如:SimpleCompletionCache,Agent 端使用 LRU 算法的 CopilotCompletionCache,Server 端也可以有自己的缓存系统。

多级缓存系统可以有效减少对后端服务的请求,提高响应速度。

LLM 的上下文工程的未来?

在互联网上,我们常常能看到一些令人惊叹的视频,展示了内存有限时代编程的奇妙创意,比如雅达利(Atari)时代、红白机等等,它们见证了第一个 8-bit 音乐的诞生、Quake 的平方根算法等等。

而在当下,LLM 正在不断地突破上下文能力的极限,比如 Claude 提供了 100K 的上下文能力,让我们不禁思考,未来是否还需要像过去那样节省 tokens 的使用。

那么,我们还需要关注 LLM 的上下文吗?

当内存有限时,程序员需要发挥想象力和创造力来实现目标。而至今我们的内存也一直不够用,因为不合格的开发人员一直浪费我们的内存。所以吧,tokens 总是不够用的,我们还是可以考虑关注于:

  1. 优化 token 分配策略:由于 token 数的限制,我们需要优化 token 分配策略,以便在有限的 token 范围内提供最相关的上下文信息,从而生成更准确、更有用的内容。

  2. 多样化的上下文信息:除了指令、示例等基本上下文信息外,我们还可以探索更多样化的上下文信息,例如注释、代码结构等,从而提供更全面的上下文信息,进一步提高 LLM 的输出水平。

  3. 探索新的算法和技术:为了更好地利用有限的资源,我们需要探索新的算法和技术,以便在有限的 token 数限制下实现更准确、更有用的自然语言处理。

  4. ……

未来,一定也会有滥用 token 程序,诸如于 AutoGPT 就是一直非常好的例子。

结论

GitHub Copilot 可以在有限的 token 范围内提供最相关的上下文信息,从而生成更准确、更有用的代码提示。这些策略提供了一定的灵活性,用户可以根据自己的需要来调整 Copilot 的行为,从而获得更好的代码自动补全体验。

我们跟进未来的路,依旧很长。

Copilot 逆向工程相关资料:

  • https://github.com/thakkarparth007/copilot-explorer

  • https://github.com/saschaschramm/github-copilot

其它相关资料:

  • https://github.com/imClumsyPanda/langchain-ChatGLM

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

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

相关文章

印刷和喷绘过程中高精度油墨流量和压力的串级控制解决方案

摘要:针对现有技术在印刷或喷绘设备中油墨流量控制不准确,使得油墨粘稠度产生异常造成批量性质量方面的问题,本文提出了相应的串级控制解决方案,即通过双回路形式同时控制油墨的流量和压力。本解决方案不仅可以保证油墨最终流量的…

【C++ 入坑指南】(07)判断

文章目录 一、if 语句1. 单行格式 if 语句2. 多行格式 if 语句 二、三目运算符三、switch 语句四、算法题4.1 分段函数 判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句&am…

C++ - 使用RBTree来封装Set与Map

前面的文章中我们简单的实现了一个红黑树,实现了它的插入的功能,在本文中我们来对其进行修改并构建Set与Map。 下面我们来从源码中截取一点有关Map与Set的代码; 可以看出,在STL30中构建Map与Set使用的是同一个红黑树模板&#xf…

开箱即用!AI模型库全新发布,一站式在线开发部署!

人工智能学习与实训社区飞桨AI Studio模型库全新升级!支持模型创建、上传、托管并一键调用模型线上开发部署! 飞桨AI Studio已接入飞桨生态特色模型库,全面覆盖模型领域,包含文心系列大模型、CV、NLP、语音、科学计算、量子计算等…

Linux常用命令——hwclock命令

在线Linux命令查询工具 hwclock 显示与设定硬件时钟 补充说明 hwclock命令是一个硬件时钟访问工具,它可以显示当前时间、设置硬件时钟的时间和设置硬件时钟为系统时间,也可设置系统时间为硬件时钟的时间。 在Linux中有硬件时钟与系统时钟等两种时钟。…

XR文字输入技术

VR/AR/MR(统称为XR)有望成为个人电脑、手机之后的下一代计算平台,元宇宙的硬件入口。 近年来XR发展迅猛,不仅可以应用于游戏、影视领域,还在军事、医疗、办公、教育等领域有巨大的发展前景。然而相比于XR强大的显示技…

IPWorks IPC .NET 2022.0.85 Crack

IPWorks IPC .NET一个组件库,用于通过命名管道向应用程序添加进程间通信 (IPC) 功能。包括客户端、服务器和外部进程执行组件,用于进程之间的简单对等通信。 最新的IPWorks IPC现已上市!最新版本的 IPWorks IPC 具有现…

我用ChatGPT搞懂GPT技术原理,只问了30个问题,这是极致的学习体验!

自己前段时间写了一篇文章《问了ChatGPT 上百个问题后,我断定ChatGPT可以重塑学习范式!》,讲了使用ChatGPT的感受,最近我开始学习GPT的技术原理,原因有三个: 1、工作中有可能要用到GPT,理解GPT的…

智见|中国能建中电工程罗必雄:数能融合为数字中国夯实底座

出品|网易科技《智见访谈》 作者|赵芙瑶 编辑|丁广胜 数字化浪潮的风,吹到了能源结构转型领域。 中国作为全球最大的能源生产国和消费国,正积极推动能源行业的数字化和智能化建设。数字化智能化升级在能源产业中被视为一项重要的战…

Go设计模式--解释器模式

大家好,这里是每周都在陪你一起进步的网管~!今天继续学习设计模式—解释器模式 解释器模式是一种行为设计模式,可以用来在程序里创建针对一个特点领域语言的解释器,用于处理解释领域语言中的语句。换句话说&#xff0c…

转转前端周刊第六十五期

转转前端周刊 本刊意在将整理业界精华文章给大家,期望大家一起打开视野 如果你有发现一些精华文章想和更多人分享,可以点击我们的公众号名称,将文章链接和你的解读文案发给我们!我们会对内容进行筛选和审核,保留你的推…

基于POM模式应用Playwright进行自动化测试

下方查看历史精选文章 重磅发布 - 自动化框架基础指南pdfv1.1大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 前言 在现代软件开发中,自动化…

【Linux】Centos安装Redis数据库并内网穿透远程连接

文章目录 前言1. Linux(centos8)安装redis数据库2. 配置redis数据库3. 内网穿透3.1 安装cpolar内网穿透3.2 创建隧道映射本地端口 4. 配置固定TCP端口地址4.1 保留一个固定tcp地址4.2 配置固定TCP地址4.3 使用固定的tcp地址连接 前言 Redis作为一款高速缓存的key value键值对的…

springboot+jsp家政预约服务管理系统

智慧家政在线预约管理系统为用户提供家政服务预约服务,系统包括前台和后台。 前台用户可以先进行注册,填写个人的基本信息提交到服务器,服务器把数据保存到数据库。管理员对会员的信息进行验证后,会员通过验证后的用户名和密码进行…

vlc搭建rtsp直播Demo ffmpeg + nginx + flv.js实现rtsp网页播放Demo

文章目录 学习链接本地视频文件作为数据源推流步骤拉流步骤 本地摄像头作为数据源拉流步骤 vlc ffmpeg nginx flv.js 实现网页视频直播概括vlc打开摄像头,提供rtsp视频流nginx配置http-flv.conf的nginx配置文件 ffmpeg将rtsp视频流转为rtmp,推送给ngi…

硬文:为什么中本聪不给比特币设计最终性?

* * * 原创:刘教链 * * * 昨日刘教链公众号刊发原创文章《论比特币和以太坊的“宕机”》之后,引发了一些对区块链工作原理感兴趣的朋友的热烈讨论。其中,魔笛手社区群主Claire提了一个好问题:为什么中本聪不给比特币设计最终性&a…

Babylon.js实战WebXR/元宇宙

从 VR 音频实验到街机上的 VR 休闲游戏,再到使用 AR 或 VR 创建新协作方式的更严肃用途,阅读本文后,你应该对今天可以做什么有很好的了解。 事实上,在本文中,我将分享我一直致力于使用 Babylon.js 构建沉浸式或增强现…

Towards Open-Set Object Detection and Discovery(论文翻译)

Towards Open-Set Object Detection and Discovery 摘要 随着人类对知识的不断追求,开集目标检测(OSOD)被设计用于识别动态世界中的未知目标。然而,当前设置的一个问题是,所有预测的未知对象共享相同的类别为“未知”…

Kali-linux使用Metasploitable操作系统

Metasploitable是一款基于Ubuntu Linux的操作系统。该系统是一个虚拟机文件,从http://sourceforge.net/projects/metasploitable/files/Metasploitable2/网站下载解压之后可以直接使用,无需安装。由于基于Ubuntu,所以Metasploitable使用起来十…

卧龙、凤雏!两源码学得一,代码质量都不会差!

作者:小傅哥 博客:https://bugstack.cn 沉淀、分享、成长,让自己和他人都能有所收获!😄 有人问我,编程能力怎么提升,我说学源码学的。他有问我,是不学 Spring 源码比学 MyBatis 更好…