从使用 Aider 编码助手后,我已经使用 Mentat 编写代码了几周。
与 Aider 的比较
它的工作方式类似。它在终端上运行,具有文本 UI。它甚至允许您设置亮暗模式颜色方案。编码会话涉及添加相关文件以获取上下文。在聊天框中,您提出愿望,它会回来与代码更改的操作计划。批准这些更改后,它们将被实施。
整体体验与 Aider 相似,除了 Aider 会为每个更改创建 git-commit(您可以选择退出)。Mentat 将版本管理留给您。
您对愿望的表达质量将决定工作的质量。您需要非常详细地表达它。无论您使用哪一个,您仍然需要像与愚昧的实习生交流一样。
上下文限制
Mentat 的缺陷之一是它支持的 LLM 列表很少(与 Aider 相比)。我没有让这成为问题,我将其与 Together.ai 中的编码 LLM 结合使用。
但是这并不重要;我一开始就遇到了上下文窗口限制。准许,我的一些文件是生产长度的,但我并没有包括太多。实际上,我甚至没有机会让它做些聪明的事情。上下文限制就是我的障碍。
解决方案不是使用上下文限制更大的 LLM。总会有一个上限,您最终会不断地撞上这个上限。
构建自己的 RAG
我听说 RAG 是答案。所以,我构建了一个中间件,它位于 Mentat 和 LLM 之间。
这是一个 OpenAI 兼容的 REST API(http://localhost:<port>/chat/completions),在本地运行,所有都在一个 Python 文件中。我称之为 Broken Sword,以便轻松引用。
对于 Mentat 来说,Broken Sword 就是一个实际的 LLM 服务。在 Broken Sword 中,我捕获 Mentat 的请求, massage 输入,发送到任何 LLM,我想,并以 OpenAI 兼容的方式返回响应。这样做时,我可以看到 Mentat 发出的详细指令,这就是 prompt-engineering 的样子。
只是这样做,我已经使 Mentat 能够使用人类可用的任何 LLM。我继续使用 Google Gemini 1.5 来为 Broken Sword 提供动力,主要是因为它具有正确的质量和成本平衡。
这本身并不能解决上下文窗口限制。这个只是一个 glorified 管道。
而不是将 Mentat 的输入 verbatim 发送,而是将大量上下文存储在向量数据库中,并将其作为嵌入发送。假如我正确理解的话,大块文本将被转换为 LLM 可以使用的多维矩阵。这些比原始文本要小得多。
我使用 LangChain(它将一系列过程抽象出来)和 Flask(用于简单的 API)来实现这一点。感觉像作弊,因为我还不知道这种魔法是如何工作的,但我想快速 hack 这些东西。他们说你不需要 LangChain,我相信他们,但总有一天,男人,一些日子。
它工作了
当我完成时,Mentat 最终像预期那样工作了。我让它编写单元测试,它写在与现有测试风格一致的方式中。我让它编写 GitHub Actions 工作流程,结果是合理的。
这非常满足人心,当它工作时。知道我已经让它与 Broken Sword 一起工作,这让我感到更加满足。
这让我想知道,为什么 Mentat 不使用 RAG 或向量数据库像我刚刚做的那样?感觉像我刚刚做的那样非常简单。我浏览了 Mentat 代码库,实际上 Chroma DB 正在使用(与我使用的向量数据库相同)。所以也许他们正在以某种方式使用 RAG,但这对我来说并不重要。
但是它很笨拙
随着我继续使用 Mentat,我注意到它的笨拙。有时它会崩溃,因为 LLM 没有返回它喜欢的东西,但大多数时候崩溃的原因我不知道。优雅的失败不是它的长处。
有时 Mentat 会在我提出请求后崩溃。重新启动后,我重新包含相关文件,并重复相同的请求(好在他们有聊天记录,可以轻松地这样做),然后一切都能正常工作。
手动编码的混合
在这次冒险中,我想回答的一个问题是,在解决一个问题时使用这种方式的编码助手和直接编辑文件的正确混合。如果可能,应该所有编码都从编码助手中完成?或者我们应该在下一个屏幕上准备好代码编辑器?
在我的情况下,Mentat 占据了屏幕的一半,另一半用于 emacs。我期望 Mentat 能够给我大多数想要的东西,但不是完美的,我将在 emacs 中对同一个文件进行少量调整。
如果 Mentat 风格的编码助手有未来,我想知道这是否应该是正确的方式。
dev.to
Deep dive into Mentat coding assistant
Create attached notes ...