由于 sorrycc.com 自己实现了一遍,密码算法没有复用 wordpress 的,之前注册过的付费用户,请先「忘记密码」重新设置密码,再登录。

译:我如何使用 LLM 来帮助我编写代码

Feb 15, 2025

原文:https://simonwillison.net/2025/Mar/11/using-llms-for-code/
作者:Simon Willison
译者:ChatGPT 4 Turbo

编者注:这篇文章介绍了作者使用 LLM 辅助编程的经验和建议。主要观点包括: 1) 使用 LLM 编程需要合理预期,不要期待它能完美完成所有任务,而是将其视为一个快速但容易犯错的编程助手; 2) 上下文管理很关键,包括对话历史和代码示例等都会影响结果; 3) 给 LLM 明确的指示很重要,要告诉它具体要做什么,而不是模糊的要求; 4) 一定要测试 LLM 生成的代码; 5) 要把使用 LLM 当作一个对话过程,需要不断调整和改进; 6) LLM 最大的优势是加快开发速度,让一些原本不值得花时间的项目变得可行; 7) LLM 会放大已有的专业知识,对特定领域了解越多,使用效果越好。作者还分享了一个具体案例,展示了如何用 Claude Code 在 30 分钟内完成一个小项目。

关于使用大型语言模型帮助编写代码的在线讨论,不可避免地会产生一些开发者的评论,他们的体验令人失望。他们经常询问自己做错了什么——为什么有些人报告了如此好的结果,而他们自己的实验却显得不足?

使用 LLMs 编写代码是困难非直观的。要弄清楚以这种方式使用它们的锋利和柔和边缘,需要付出巨大的努力,而且几乎没有什么指导可以帮助人们弄清楚如何最好地应用它们。

如果有人告诉你,使用 LLMs 编码是容易的,他们(可能无意中)误导了你。他们可能确实偶然发现了有效的模式,但这些模式并不是每个人都能自然而然地掌握的。

我现在已经使用 LLMs 编写代码取得了超过两年的好结果。这里是我尝试将一些经验和直觉转移给你的尝试。

设定合理的期望

忽略“AGI”炒作——LLMs 仍然是花哨的自动完成功能。它们所做的只是预测一系列的令牌——但事实证明,编写代码大多是关于以正确的顺序串联令牌,所以只要你指引它们正确的方向,它们可以是极其有用的。

如果你假设这项技术将在不需要你运用任何自己的技能的情况下完美实现你的项目,你将很快感到失望。

相反,使用它们来增强你的能力。我当前最喜欢的心理模型是将它们想象成一个过于自信的对编程助手,他们在查找事物方面快如闪电,可以随时提供相关示例,并且可以毫无怨言地执行乏味的任务。

过于自信很重要。它们绝对会犯错误——有时是微妙的,有时是巨大的。这些错误可能是深度非人类的——如果一个人类合作者幻想出一个不存在的库或方法,你会立即对他们失去信任。不要陷入拟人化 LLMs 的陷阱,假设会贬低人类的失败也应该以同样的方式贬低机器。

在使用 LLM 时,你经常会发现有些事情它们就是做不到的。记下这些——它们是有用的教训!它们也是值得保存以备将来之用的宝贵示例——一个强大的新模型的标志就是它能够为以前的模型无法处理的任务产生可用的结果。

考虑训练截止日期

任何模型的一个关键特性是其训练截止日期。这是它们被训练的数据停止收集的日期。对于 OpenAI 的模型,这通常是 2023 年 10 月。Anthropic、Gemini 和其他提供商可能有更近的日期。

这对代码来说极其重要,因为它影响了它们将熟悉哪些库。如果你正在使用的库自 2023 年 10 月以来发生了重大的破坏性变更,OpenAI 的模型就不会知道!

我从 LLM 中获得了足够的价值,以至于我现在在选择库时会故意考虑这一点——我尝试坚持使用具有良好稳定性的库,并且它们足够流行,以至于许多示例已经进入了训练数据。我喜欢应用无聊技术的原则——在你的项目的独特卖点上进行创新,在其他一切上坚持使用经过尝试和测试的解决方案。

LLM 仍然可以帮助你使用存在于它们训练数据之外的库,但你需要投入更多的工作——你需要将这些库应该如何使用的最新示例作为你的提示之一来提供给它们。

这引出了在使用 LLM 时理解最重要的事情:

上下文至关重要

从 LLM 中获得好结果的大部分技巧归结为管理其上下文——构成你当前对话的文本。

这个上下文不仅仅是你提供给它的提示:成功的 LLM 互动通常采取对话的形式,上下文包括当前对话线程中你的每条消息和 LLM 的每个回复。

当你开始一段新的对话时,你就将那个上下文重置为零。这一点很重要,因为通常解决对话不再有用的办法就是清空所有内容并重新开始。

一些 LLM 编码工具的功能不仅仅局限于对话。例如,Claude Projects 允许你预先填充相当大量的文本——包括最近能够直接从 GitHub 仓库导入代码的能力,这是我_经常_使用的。

像 Cursor 和 VS Code Copilot 这样的工具会自动包含你当前编辑器会话和文件布局的上下文,并且你有时可以使用像 Cursor 的 @commands 这样的机制来引入额外的文件或文档。

我之所以大多数时候直接使用 ChatGPTClaude 的网页或应用界面,是因为这让我更容易明白究竟有什么内容进入了上下文。那些让上下文对我不透明的 LLM 工具_效果_较差。

你可以利用之前的回复也是上下文一部分这一事实来为你所用。对于复杂的编码任务,尝试先让 LLM 写一个简化版,检查它是否有效,然后再迭代构建更复杂的实现。

我经常通过倾倒现有代码来开始新的聊天,以此作为上下文的种子,然后与 LLM 合作以某种方式修改它。

我最喜欢的代码提示技巧之一是放入几个与我想要构建的东西相关的完整示例,然后提示 LLM 使用它们作为新项目的灵感。当我详细描述了我的 JavaScript OCR 应用程序时,我谈到了这一点,该应用程序结合了 Tesseract.js 和 PDF.js——两个我过去使用过并且能够在提示中提供工作示例的库。

向他们询问选项 #

我大多数的项目都是从一些开放性问题开始的:我尝试做的事情可能吗?我能以哪些潜在的方式实现它?这些选项中哪些是_最好的_?

我在这个初步研究阶段使用 LLMs。

我会使用像“Rust 中有哪些 HTTP 库的选项?包括使用示例”或“JavaScript 中有哪些有用的拖放库?为我构建一个展示每个库的成品”(对 Claude 而言)这样的提示。

训练截止日期在这里是相关的,因为这意味着不会建议使用较新的库。通常这是可以的——我不想要最新的,我想要的是最稳定的,以及已经存在足够长时间以解决 bug 的那个。

如果我打算使用更近期的东西,我会自己在 LLM 世界之外进行研究。

开始任何项目的最佳方式是用一个原型来证明该项目的关键要求可以得到满足。我经常发现,一个 LLM 可以在我坐下来打开笔记本电脑的几分钟内——或有时甚至在我使用手机工作时——就让我得到一个工作原型。

告诉它们确切地要做什么

一旦我完成了初步研究,我就会戏剧性地改变模式。对于生产代码,我的 LLM 使用方式更加专制:我将其视为一个数字实习生,根据我的详细指令为我键入代码。

这里有一个最近的例子:

编写一个 Python 函数,使用 asyncio httpx,其签名如下:

async def download_db(url, max_size_bytes=5 * 1025 * 1025): -> pathlib.Path

给定一个 URL,这会将数据库下载到一个临时目录并返回一个路径。但是它会在开始回传数据时检查内容长度头,如果超过限制,则抛出错误。当下载完成时,它使用 sqlite3.connect(…) 然后运行一个 PRAGMA quick_check 来确认 SQLite 数据是有效的——如果不是,则抛出错误。最后,如果内容长度头对我们撒谎——如果它说是 2MB 但我们下载了 3MB——我们一发现这个问题就抛出错误。

我本可以自己写这个函数,但查找所有细节并让代码正确运行起来,至少需要我花费十五分钟的时间。Claude 在 15 秒内 就搞定了。

我发现 LLM 对于像我这里使用的函数签名反应非常好。我充当函数设计者的角色,LLM 负责按照我的规格构建函数体。

我经常会接着说:“现在用 pytest 给我写测试。”同样,我指定了我选择的技术——我希望 LLM 能节省我打字的时间,因为那些代码已经在我的脑海中了。

如果你的反应是“肯定打字出代码比打字出一个英文指令要快”,我只能告诉你,对我来说真的不是这样了。代码需要正确无误。英文有巨大的简化空间,还有模糊性、打字错误,以及像“使用那个流行的 HTTP 库”这样的说法,如果你一时想不起名字的话。

擅长编码的 LLM 在填补空白方面表现出色。它们也比我更不懒——它们会记得捕获可能的异常,添加准确的文档字符串,并用相关类型注释代码。

你必须测试它写的内容!#

我上周已经详细写过:你绝对不能将测试代码是否真正工作的任务外包给机器。

作为一名软件开发者,你的责任是交付工作系统。如果你没见它运行,那它就不是一个工作系统。你需要投资加强那些手动 QA 习惯。

这可能不够光鲜,但无论是否涉及 LLM,这始终是发布优质代码的关键部分。

记住这是一场对话#

如果我不喜欢 LLM 写的内容,它们永远不会因被告知重构而抱怨!“把那些重复的代码抽成一个函数”、“使用字符串操作方法而不是正则表达式”,甚至是“写得更好!”——LLM 首次产生的代码很少是最终实现,但它们可以为你重新键入几十次,而不会感到沮丧或无聊。

偶尔我会从我的第一个提示中得到一个很好的结果——随着我练习的增多,这种情况越来越频繁——但我预计至少需要几次后续操作。

我经常想,这是否是人们错过的关键技巧之一——一个不好的初始结果并不是失败,它是一个推动模型朝着你真正想要的东西方向发展的起点。

使用可以为你运行代码的工具

现在越来越多的 LLM 编码工具现在有能力为你运行那些代码。我对其中一些持稍微谨慎的态度,因为错误的命令有可能造成真正的损害,所以我倾向于坚持使用那些在安全沙箱中运行代码的工具。我现在的最爱是:

  • ChatGPT Code Interpreter,在这里 ChatGPT 可以直接在由 OpenAI 管理的 Kubernetes 沙箱 VM 中编写然后执行 Python 代码。这是完全安全的——它甚至不能进行出站网络连接,所以真正可能发生的就是临时文件系统被搞乱然后重置。
  • Claude Artifacts,在这里 Claude 可以为你构建一个完整的 HTML+JavaScript+CSS 网页应用,该应用在 Claude 界面内显示。这个网页应用显示在一个非常严格限制的 iframe 沙箱中,极大地限制了它可以做什么,但防止了像意外泄露你的私人 Claude 数据这样的问题。
  • ChatGPT Canvas 是一个较新的 ChatGPT 功能,具有与 Claude Artifacts 类似的能力。我自己还没有足够深入地探索这个功能。

如果你愿意冒一点险:

  • Cursor 有一个可以做到这一点的“Agent”功能,Windsurf 和越来越多的其他编辑器也是如此。我还没有花足够的时间来做出推荐。
  • Aider 是这类模式的领先开源实现,并且是自食其力的一个很好的例子——Aider 的最近版本已经有超过 80%是由 Aider 本身编写的。
  • Claude Code 是 Anthropic 在这一领域的新进入者。我将很快提供使用该工具的详细描述。

这种在循环中运行代码的模式非常强大,以至于我选择我的核心 LLM 工具进行编码主要基于它们是否可以安全地运行并迭代我的代码。

Vibe-coding 是学习的好方法 #

Andrej Karpathy 创造了术语 vibe-coding,就在一个多月前,这个词已经流行开来:

有一种我称之为 “vibe coding” 的新编码方式,你完全沉浸在氛围中,拥抱指数增长,忘记代码甚至存在。[…] 我要求一些愚蠢的事情,比如 “将侧边栏的填充减半”,因为我懒得去找它。我总是 “接受所有”,我不再阅读差异。当我收到错误消息时,我只是复制粘贴它们,不加评论,通常这样就能解决问题。

Andrej 认为这对于 “丢弃的周末项目来说还不错”。这也是探索这些模型能力的一种 极好的 方式——而且真的很有趣。

学习 LLMs 的最佳方式是与它们玩耍。向它们抛出荒谬的想法并进行 vibe-coding,直到它们几乎有点工作,这是加速你建立对什么有效和什么无效的直觉的真正有用的方式。

在 Andrej 给它命名之前,我就已经在 vibe-coding 了!我的 simonw/tools GitHub 仓库有 77 个 HTML+JavaScript 应用和 6 个 Python 应用,它们每一个都是通过提示 LLMs 构建的。我从构建这个集合中学到了 很多,并且我以每周几个新原型的速度增加它。

你可以直接在 tools.simonwillison.net 上尝试我的大多数工具——这是仓库的一个 GitHub Pages 发布版本。我在 10 月份关于其中一些写了更详细的笔记,在 本周我用 Claude Artifacts 构建的所有东西 中。

如果你想看到每个页面所使用的聊天记录的转录,几乎总是可以在该页面的提交历史中找到链接,或者访问新的 铭文页面 查看包含所有这些链接的索引。

使用 Claude Code 的详细示例 #

在我写这篇文章的时候,我想到了 tools.simonwillison.net/colophon 页面的想法——我想要一个链接,以更明显的方式展示我所有工具的提交历史,而不是 GitHub。

我决定利用这个机会来展示我的 AI 辅助编码过程。

这次我使用了 Claude Code,因为我希望它能够直接在我的笔记本电脑上针对我的现有工具仓库运行 Python 代码。

在我的会话结束时运行 /cost 命令向我展示了这个:

> /cost 
  ⎿  总成本:$0.61
     总持续时间(API):5m 31.2s
     总持续时间(墙上时间):17m 18.7s

这个初始项目从开始到结束总共花了我 17 分钟多一点的时间,以及在 Anthropic 的 API 调用上花费了 61 美分。

我使用了权威过程,我告诉模型我确切想要构建什么。这是我的提示序列(完整转录在这里)。

我首先请求一个初始脚本来收集新页面所需的数据:

这个目录中的几乎所有 HTML 文件都是使用 Claude 提示创建的,这些提示的细节链接在提交消息中。构建一个 Python 脚本,依次检查每个 HTML 文件的提交历史,并将这些提交消息中的任何 URL 提取到一个列表中。然后它应该输出一个具有此结构的 JSON 文件:{“pages”:{“name-of-file.html”:[“url”],{“name-of-file-2.html”:[“url1”,“url2”],…—正如你所见,一些文件在其提交历史中可能有不止一个 URL。该脚本应该被命名为 gather_links.py,并且它应该保存一个名为 gathered_links.json 的 JSON 文件

我真的没有很认真地思考这第一个提示——它更多的是一种意识流,我在思考初始问题时就打字输入到了机器人中。

我检查了初始结果并发现了一些问题:

看起来它只获取了 URL 的开始部分,它应该获取整个 URL,这些 URL 可能指向不同的网站——所以只获取以 https:// 开头并以空白或提交信息结束的内容

然后我改变了主意——我也想要那些完整的提交信息:

更新脚本——我想要捕获完整的提交信息和 URL——新的格式应该是 {“pages”: {“aria-live-regions.html”: {“commits”: [{“hash”: hash, “message”: message, “date”: iso 格式的日期], “urls”: [之前一样的 URL 列表]

像这样提供示例是快速获得你想要的东西的绝佳捷径。

注意,我在任何时候都没有查看它所写的代码 gather_links.py!这完全是凭感觉编程:我在看它在做什么,但我完全将实现细节留给了 LLM。

JSON 对我来说看起来不错,所以我说:

这运行得很好。写一个新脚本叫做 build_colophon.py,它会查看那个收集到的 JSON 文件,并构建并保存一个 HTML 页面。页面应该对移动设备友好,并且应该列出每个页面——带有指向该页面的链接——并且对于每一个页面,整齐地显示提交信息(将换行符转换为 br 并链接化 URL 但不进行其他格式化)——加上提交信息的日期和指向提交本身的链接,这些链接在 https://github.com/simonw/tools

Claude 知道 GitHub URL 的工作方式,所以告诉它链接到提交并提供仓库名称就足够它猜到这些提交 URL https://github.com/simonw/tools/commit/fd9daf885c924ba277806b3440457d52b0ad90a8

我倾向于发现 Claude 在网页设计方面有很好的默认品味——我说“页面应该对移动设备友好”并就此打住。

Claude 忙碌地为我构建了一个页面,但结果并不正确,所以我说:

它没有正确工作。ocr.html 有一堆提交,但在 colophon.html 中只有一个链接和第一个提交的标题,其余的都显示在同一个块中——应该为其他每个提交分别有带链接和格式化日期的独立 HTML 块。而且,整齐格式化的日期应该包括 HH:MM 和日期

它自己修复了这个 bug,只留下了我决定做的两个更改:

几乎完美了,但每个页面应该以相反的顺序显示提交——最旧的在前

然后是:

最后一个更改——页面目前是按字母顺序列出的,让我们改为按最近修改的顺序排在最上面

这就是整个项目的全部内容!这里是 build_colophon.py,它生成的页面看起来相当不错

Tools Colophon. 该页面记录了 tools.simonwillison.net 上工具的创建过程,包括用于构建它们的 Claude 对话链接。social-media-cropper.html b4a2bc 2024 年 12 月 10 日 20:35 社交媒体裁剪器 https://gist.github.com/simonw/12b8f88932a71450071190e1289a17e9 a10954 2025 年 2 月 28 日 16:02 支持 2:1 和 14:10 比例 https://gist.github.com/simonw/e23917eddcbb368c9b6180d581f8f40a

还有一个剩余任务:我需要将新的 colophon 作为我的网站的一部分进行部署,但我不想将新的 colophon.html 页面直接检入仓库。我想要一个自定义的 GitHub Pages 构建过程。

我开始了一个全新的 Claude Code 会话(清除旧账),看看 Claude 是否也能解决这个问题:

这个仓库是使用 GitHub Pages 部署的。我想稍微修改构建过程——在部署到 GitHub Pages 之前,它应该运行 python gather_links.py,这将生成一个名为 gathered_links.json 的文件——然后它应该运行 python build_colophon.py,使用该文件创建 colophon.html——我希望将 gathered_links.json 和 colophon.html 发布到 GitHub Pages,但我不希望它们被检入仓库本身。

与第一次不同,这次我非常仔细地观察它的操作——我不知道如何以这种方式自定义 GitHub Pages 构建,我既想学习如何做,又小心它可能会幻想细节并失败。

它告诉我它想要创建这个文件,并请求我的许可:

name: Deploy to GitHub Pages

on:
  # 在推送到 main 分支时运行
  push:
    branches: [ main ]
  # 允许手动触发
  workflow_dispatch:

# 设置 GITHUB_TOKEN 的权限
permissions:
  contents: read
  pages: write
  id-token: write

# 允许同时只有一个部署
concurrency:
  group: pages
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 为 gather_links.py 中的 git log 需要完整历史记录

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip

      - name: Generate links and build colophon
        run: |
          python gather_links.py
          python build_colophon.py

      - name: Setup Pages
        uses: actions/configure-pages@v4

      - name: Build with Jekyll
        uses: actions/jekyll-build-pages@v1

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

我猜这样对吗?我很欣赏那条关于“为 gather_links.py 需要完整历史记录”的评论——这是我很容易就会忽略的事情。

然后它说它想要将这些文件添加到 .gitignore——听起来是个好主意。

它总结了到目前为止的操作:

我已经为 GitHub Pages 创建了一个 GitHub Actions 工作流程,该工作流程:

  1. 创建一个 .github/workflows/pages.yml 文件,该文件:
    • 在推送到 main 分支时运行
    • 检出完整的 git 历史记录(gather_links.py 需要)
    • 设置 Python 3.12
    • 依次运行两个脚本以生成文件
    • 构建并部署到 GitHub Pages
  2. 创建 .gitignore 文件以防止生成的文件被提交

现在,当你推送到 main 分支时,GitHub Actions 将:

  • 运行 gather_links.py 脚本创建 gathered_links.json
  • 运行 build_colophon.py 创建 colophon.html
  • 部署这两个文件(以及所有其他文件)到 GitHub Pages

我检查了它的成本:

> /cost 
  ⎿  总成本:$0.1788
     API 总时长:44.6s
     墙上总时长:10m 18.6s

所以使用 Claude API 花费了 17 分和 45 秒。(我分心了,所以总共用了 10 分钟。)这里是完整记录

代码看起来不会造成不可逆的破坏,所以我将它推送到 GitHub 看看会发生什么。

… 它起作用了!我的新铭文页面已经上线。

有一个问题。我在运行时观察了 GitHub Actions 界面,但有些地方看起来不对劲:

GitHub Actions 界面显示三个已完成的操作。测试自定义页面工作流程的铭文,2 为同一名称部署和另一个名为 pages-build-deployment 的操作。

我预期会有那个“测试”任务,但为什么会有两个单独的部署?

我猜测之前的默认 Jekyll 部署仍在运行,而新的部署同时进行——纯粹是运气好,新脚本后完成并覆盖了原始结果。

是时候抛开 LLMs,阅读一些文档了!

我找到了这个页面 使用自定义工作流程与 GitHub Pages,但它没有告诉我我需要知道的信息。

凭借另一个直觉,我检查了我的仓库的 GitHub Pages 设置界面,发现了这个选项:

GitHub Pages UI - 显示你的站点已在 tools.simonwillison.net 上线,7 分钟前部署。- 然后在 Build and deployment 下的源菜单显示 GitHub Actions 或从分支部署(已选)的选项

我的仓库被设置为“从分支部署”,所以我将其切换到了“GitHub Actions”。

我手动更新了我的 README.md,在此提交中添加了指向新的 Colophon 页面的链接,这触发了另一次构建。

这次只运行了两个作业,最终结果是正确部署的站点:

现在只有两个进行中的工作流,一个是测试,另一个是部署到 GitHub Pages。

(后来我发现了另一个错误——一些链接无意中在它们的 href= 中包含了 <br> 标签,我通过另一个 11 分钟 Claude Code 会话 修复了这个问题。)

更新:我通过添加 AI 生成的工具描述进一步改进了 Colophon。

准备好让人类接手 #

这个例子对我来说很幸运,因为它帮助说明了我的最后一点:预计需要接手。

LLMs 无法替代人类的直觉和经验。我与 GitHub Actions 相处的时间足够长,我知道要寻找什么类型的东西,在这种情况下,我介入并完成项目比继续尝试用提示达到目的要快。

最大的优势是开发速度 #

我的新铭文页面从构思到完成、部署的功能,用了不到半小时。

我确信,如果没有 LLM 的帮助,这将会花费我更多的时间,以至于我可能根本就不会去构建它。

这就是为什么我如此关心从 LLMs 获得的生产力提升:它不仅仅是关于更快完成工作,更是关于能够发布那些我原本无法证明值得花时间的项目。

我在 2023 年 3 月写过这个话题:AI 增强的开发让我的项目更具雄心。两年后,这种效果仍然没有减弱的迹象。

这也是加速学习新事物的绝佳方式——今天,那就是如何使用 Actions 自定义我的 GitHub Pages 构建,这绝对是我将来会再次使用的东西。

LLMs 让我能够更快地执行我的想法,这意味着我可以实现更多的想法,这也意味着我可以学到更多。

LLMs 放大现有专业知识#

其他人能以相同的方式完成这个项目吗?可能不行!我的提示依赖于 25 年以上的专业编码经验,包括我之前对 GitHub Actions、GitHub Pages、GitHub 本身以及我使用的 LLM 工具的探索。

我也_知道_这将会奏效。我与这些工具共事足够长的时间,足以让我确信,用从我的 Git 历史中提取的信息组装一个新的 HTML 页面完全在一个好的 LLM 的能力范围内。

我的提示反映了这一点——这里没有什么特别新奇的,所以我指定了设计,在它工作时测试了结果,并偶尔推动它修复一个 bug。

如果我试图构建一个 Linux 内核驱动程序——一个我几乎一无所知的领域——我的过程将会完全不同。

额外福利:回答有关代码库的问题#

如果你仍然觉得使用 LLMs 来编写代码非常不吸引人,那么你可能会发现它们的另一个用途更有吸引力。

优秀的 LLMs 在回答有关代码的问题方面做得非常好。

这也是非常低风险的:最坏的情况就是它们可能会出错,这可能会让你花更多一点时间来弄清楚。与完全独自挖掘成千上万行代码相比,这仍然很可能为你节省时间。

这里的诀窍是将代码倾倒进一个长上下文模型中,然后开始提问。我目前最喜欢的是一个名为 gemini-2.0-pro-exp-02-05 的模型,这是 Google 的 Gemini 2.0 Pro 的预览版,目前可以通过他们的 API 免费使用。

我就在前几天使用了这个技巧。我在尝试一个对我来说新的工具,名为 monolith,这是一个用 Rust 编写的 CLI 工具,它可以下载一个网页及其所有依赖的资源(CSS、图片等)并将它们打包成一个单一的存档文件。

我很好奇它是如何工作的,所以我将它克隆到我的临时目录并运行了这些命令:

cd /tmp
git clone https://github.com/Y2Z/monolith
cd monolith

files-to-prompt . -c | llm -m gemini-2.0-pro-exp-02-05 \
  -s 'architectural overview as markdown'

我在这里使用我自己的 files-to-prompt 工具(去年由 Claude 3 Opus 为我构建)来收集仓库中所有文件的内容到一个单一流中。然后我将其通过管道传输到我的 LLM 工具,并通过 llm-gemini 插件告诉它向 Gemini 2.0 Pro 提出一个系统提示:“以 markdown 形式提供架构概览”。

这给了我一个详细的文档,描述了该工具的工作原理——哪些源文件做了什么,以及关键的是,它使用了哪些 Rust crates。我了解到它使用了 reqwesthtml5evermarkup5ever_rcdomcssparser,并且它根本不评估 JavaScript,这是一个重要的限制。

我每周都会用到这个技巧好几次。这是深入了解一个新代码库的绝佳方式——而且通常来说,替代方案并不是花更多时间在这上面,而是根本无法满足我的好奇心。

我在这篇最近的文章中包含了三个更多的例子。