在Emacs中使用copilot.el补全代码

谁能做个codegeex的emacs插件就好,感觉这个国产的补全很不错,而且免费.和copilot不相上下.

已经有copilot的账户的同学,除了copilot.el非常好必须得用,也推荐GitHub - chep/copilot-chat.el: Chat with Github copilot in Emacs !,
流量是免费的,可以切换gpt模型和claude。

不过说实话由于deepseek和gemini这两个模型已经太便宜了,就算有copilot账户,copilot-chat.el也没多少优势了,因为有gptel的存在。如果用deepseek or gemini这两个便宜的模型,emacs AI助手还是gptel,以及基于gptel的更好。

之前工作中一直用 phpstorm + github copilot 非常好用,只是用来生成。最近试了试 vscode 的,发现还有编辑的功能,比补全更近了一步。这两天打算捡起不用多年的 Emacs,好奇目前 AI 在 Emacs 中的效果,特别是编程方面的,copilot.el 和官方的比效果如何呢?特别是 neovim 的,毕竟 vscode 是亲生的,肯定比不上,其他的也很有名。

哈哈哈老哥很久没用Emacs了啊,补全我还没用AI,但生成方面,可以看看Aidermacs:

2 个赞

copilot.el 用的就是官方的客户端,只是包装到了 emacs 里,所以能力上是一样的,只是交互可能有些功能没有 VSCode 那么花哨。

如果只是用自动补全,copilot.el 非常好用。
如果是类似聊天对话让它替你编辑,那可以考虑楼上推荐的 aider,它比微软的 copilot chat 好用多了。

截屏2025-03-21 12.52.15

对gptel-aibo来说,这很普通~

楼上提到的 gptel-aibo 是一个不错的选择。

除此之外也可以考虑 minuet-ai.el,它提供了类似 copilot 的悬浮 ghost text 的 UI 交互体验。我是这个插件的作者,有问题欢迎问我。

需要注意的是 minuet 仅提供补全功能。

如果想要使用基于 chat 的和 LLM 进行多轮对话修改代码的体验,可以使用 aidermacs 或者 gpetl (以及楼上基于 gptel 的拓展插件 gptel-aibo)

2 个赞

为 minuet 打 call。目前我自己已经停用了 copliot.el 改用 minuet

minuet 唯一缺点是似乎只能传递单 buffer 的上下文到 api,copilot.el 我观察到会记得自己在别的 buffer(文件)中看到过的内容。不过差不多够用了

简单试过了上面提到的工具,初步的印象:

工具 第三方依赖 API 费用 备注
gptel 花钱 聊天功能,容易理解是工作原理,方便提前预估 token 数量
copilot-chat 免费 代码聊天,它直接调用 GitHub Copilot Chat 官方接口
aidermacs aider (Python 命令行工具) 花钱 代码编辑,类似 GitHub Copilot 官方的 Edit 功能,选择项目文件,按指令编辑
minuet 花钱 代码补全,这是这个包中代码量最少的,应该也是最简单的库了,上下文理解能力估计不强 |
copilot @github/copilot-language-server (NPM 包) 免费 代码补全,通过微软官方 LSP 服务实现,但我对 LSP 在 Emacs 中印象不够好

可能受制于 Emacs 环境,代码实时补全的用户体验都不行,和 VS Code 没法儿比。

2 个赞

纠正一下哈。

copilot 免费的每个月补全数量是有限额的。

但是 minuet 你可以切换不同的免费模型用,使用数量是无上限的。

我在 README 里有写的,哪些模型是免费的。目前 codestral 和 gemini 都是免费的。而且除此之外还有硅基流动也可以用免费的,选 FIM 模型, 7b 模型就够了。

而且如果你的 gpu 很强,可以直接运行本地的模型,本地模型通常配合 aider 之类的这种对智能要求比较高的任务其实差点意思,但是用来补全是够用的,7b 模型就完全够了

补全本身确实比基于聊天的交互要简单很多,这个没什么好说的。

2 个赞

似乎只能传递单 buffer 的上下文到 api

可以传递多 buffer 的内容的。对于 chat-LLM (如 gemini,claude 等通过 conversatipn 的形式调 API 的模型)可以通过 customize minuet-default-chat-input-template 这个变量来实现将多 buffer 的内容传入 prompt。

对于 FIM model (如 qwen-2.5-coder,starcoder 等本地模型,或者是 codestral 这样通过直接传入 prompt 本身来调 API 的模型)可以通过 customize minuet-openai-fim-compatible-options :template :prefix 这个函数来传入多 buffer 的上下文。

需要注意的是不同的 FIM 模型对于 repo context 的 special tokens 是不同的。有的 FIM 模型支持 通过special tokens 来识别不同的文档的内容,有的 FIM 模型压根就不支持。比如 Qwen-2.5-coder 是支持通过 <|file_sep|> 作为 special token 来作为分隔符区分不同的文件。但也正因为不同的 FIM 模型的 支持力度不同,形式也不统一,special token 也不一样。因此这个东西的定制性太强了,不好做成统一的。

具体的可以看一下 minuet 的 github repo 里的 recipes.md 里面有详细的介绍该如何去 customize 这些 prompt 变量。

毕竟咱是 emacs 用户 嘛,API 的接口已经提供了, prompt 的生成方式当然是用户发挥自己创造力的时刻了。

接下来是有几个选择什么样的多 buffer 的内容注入的思路。

第一种是通过 RAG 的方式,用 elisp 来做 rag 感觉不太好做。目前有一个 github 项目: Davidyz/VectorCode 是一个 python 项目。他提供了一个命令行接口,也提供了 MCP 的接口。可以通过传递当前 buffer 的 content,来获得想要获取的 RAG 文档。然后将 RAG 文档传入 prompt。

第二种思路不需要 RAG,也比较简单。我感觉早期的 github copilot 应该也是这个思路。就是直接从你最近访问过的 buffer 并且相同编程语言的,然后从那个 buffer 的 point 处附近抽取一定的上下文去注入。

第三个也是我接下来有时间就准备做的一个方案,我打算把 aider 的 repomap 的那部分做成一个单独的 CLI,然后就可以把 repomap 注入到 LLM 的 prompt 里去。这个 repomap 因为是基于 treesitter ,速度较快,而且不需要像 RAG 那样还需要配置本地的向量化数据库,以及计算 embedding 等操作。当然也有缺点就是支持的语言较有限。

1 个赞

lsp-bridge 也支持 github copilot,而且 copilot.el 一样都是 lsp 方案,这两者使用上有区别吗?

lsp-bridge 感觉设置有点复杂,等有机会再试试看。

copilot.el 只有一千行代码,功能简陋也可以理解。

lsp-bridge 里面的 copilot 方案是移植 vim 的,版本很老了,也好久没维护了。

现在 copilot 是官方出 npm 包,lsp-bridge 没有跟进。

使用没区别,直接补全

copilot 免费了?

lsp-bridge 也支持 github copilot,而且 copilot.el 一样都是 lsp 方案,这两者使用上有区别吗?

copilot.el 是通过 overlay 的类似 ghost text 那样的 UI。lsp-bridge 是弹窗补全。

copilot.el 只有一千行代码,功能简陋也可以理解。

copilot.el 已经实现 project goal 了,就是代码补全。建立和 copilot lsp 的连接,发送 completion 请求,以及绘制 overlay UI。那 copilot.el 还需要什么其他的功能呢,并不能说它简陋吧?

lsp-bridge 里面的 copilot 方案是移植 vim 的,版本很老了,也好久没维护了。 现在 copilot 是官方出 npm 包,lsp-bridge 没有跟进。

现在官方推出的 lsp 就是在以前 vim 版本上继续维护发布的。实质上的功能还是一样的。

需要注意的是,copilot 仅仅只是利用了 LSP 协议的 json RPC 规范进行通信而已。实际上它实现的都是私有方法,而不是 LSP 协议规范的方法。因此如果使用一个通用的 LSP client 其实是使用不了任何 copilot 的功能的。

在 LSP 最新规范 3.18 里,一些 copilot 的私有方法升级成为了规范的一部分 (主要就是加入了新的请求方法 inlineCompletion),因此如果 LSP client 实现了最新的规范,将能够支持使用 copilot 进行补全。但是 copilot 的私有方法仍然提供了比列入规范的 inlineCompletion 更多的功能。

注意的是 lsp-bridge 对 copilot 的支持也是单独实现了一个 core/copilot.py 进行支持,而不是将 copilot 当作一个普通的 lsp 进行对待。

因此在 emacs 里使用 copilot,最好还是使用 copilot.el 或者用 lsp-bridge 利用其专门实现的 copilot 支持

1 个赞

哦,copilot.el 自己调用了 github copilot 的 lsp 服务,之前没想道这一点,以为是依赖 eglot、lsp-mode 的。

还没有日常用过,感觉不大现实,之前一直用 phpstorm 的,也试过 vscode 的,都是非常强大的,用户体验肯定是比不了。感觉可以对标官方的 neovim 实现,有机会试试看 neovim 的咋样,copilot.el 应该参考了它的实现。

哥,还没用过就直接下结论不太合适吧,请求都是 copilot lsp 在后台完成的。 不管是 emacs/neovim 都只是发送一个请求而已,补全的效果如何全看后台返回什么结果就是什么结果。

1 个赞

我没买copilot就一直没用过,现在有没有什么开源做的比较好的copilot类后端lsp-bridge可以/应该接上的?

确实,没有多少机会试。

我刚刚试了试编辑 Emacs Lisp

  • 这个好像当前 Buffer 级别的,没有项目的概念,比如不支持同一项目中别的文件中的上下文
  • 用起来响应挺快,可能是比较轻量的关系
  • 比完全没有好太多了