jixiaxue 知识库
blog / simon-willison-blog / 2026-02-26-digest

Simon Willison 博客 2026-02-26 结构化总结

2026-02-26

Simon Willison 博客 2026-02-26 结构化总结

来源:simonwillison.net | 文章数量:4 篇 | 生成日期:2026-02-27


总体概述

Simon Willison 在 2026 年 2 月 26 日发布的 4 篇内容围绕一个核心主题展开:AI 编程代理正在从根本上重塑软件开发的工作方式。主文章提出了一套实战方法论——通过囤积可运行代码示例来放大编程代理的效能;Karpathy 的引用佐证了这一转变的突然性和颠覆性;Google API 密钥事件则揭示了 AI 产品快速扩张带来的安全隐患;Benedict Evans 的评论则从商业角度审视了 OpenAI 面临的产品市场契合度困境。


各篇核心要点

篇一:囤积你知道怎么做的事情

这是 Simon Willison「代理工程模式」(Agentic Engineering Patterns)系列指南中的一篇。核心论点是:软件开发者应系统性地积累可运行的代码示例和解决方案——通过博客、TIL 笔记、GitHub 仓库、HTML 工具页等形式。这些”囤积品”在编程代理时代变得极其有价值,因为代理可以直接读取、组合、复用这些示例来构建全新工具。

Willison 以自己的浏览器端 OCR 工具为例:他将之前分别验证过的 Tesseract.js(OCR 库)和 PDF.js(PDF 渲染库)的代码片段作为提示输入 Claude 3 Opus,几分钟内就得到了一个功能完整的组合工具。他强调,编程代理意味着我们只需要弄清楚一个有用的技巧一次——只要有可运行的示例记录在案,代理就能在未来无限次地复用它。

篇二:引用 Andrej Karpathy

Karpathy 指出编程在过去两个月经历了剧变——不是渐进式的,而是在 2025 年 12 月出现了断崖式的跃迁。编程代理从”基本不能用”变为”基本能用”,模型在质量、长期连贯性和韧性方面有了显著提升,足以对默认编程工作流产生颠覆性影响。这段引用与 Willison 自身对编程代理价值的论述形成了有力的呼应。

篇三:Google API 密钥安全事件

Truffle Security 发现了一个严重的安全问题:Google Maps API 密钥本设计为可公开嵌入网站的标识符,但当 Google 在相同项目上启用 Gemini API 后,这些密钥获得了访问敏感端点和计费服务的权限,构成了实质性的权限提升——而开发者从未收到警告。在 2025 年 11 月的 Common Crawl 数据中已发现 2,863 个此类暴露密钥,部分甚至属于 Google 自己。这一事件揭示了大型平台在快速推出 AI 服务时可能忽视的安全连锁反应。

篇四:引用 Benedict Evans

Evans 对 OpenAI 的商业模式提出尖锐质疑:如果用户每周最多使用几次,日常想不到用途,那就说明产品并没有真正改变用户的生活。OpenAI 所说的”能力差距”(capability gap),本质上是缺乏清晰的产品市场契合度。其广告项目既是为了覆盖免费用户的基础设施成本,更是为了在战略上能给免费用户提供最新、最强大的模型以提升参与度。


关键洞察

1. 编程代理正在经历”从不能用到能用”的相变

Karpathy 和 Willison 的观点高度一致:2025 年 12 月是一个分水岭。编程代理不再是玩具,而是真正可用的生产力工具。这不是渐进改善,而是质变。

2. “知识囤积 + 代理复用”构成新的开发者核心竞争力

Willison 提出的方法论暗示了开发者价值的重新定义:未来的核心竞争力不仅是”能写代码”,更是”拥有经过验证的可复用知识库”。代理能力越强,你的知识库就越有杠杆效应。

3. AI 快速扩张带来的安全债务不容忽视

Google API 密钥事件是一个典型案例:当 AI 服务(Gemini)被叠加到已有基础设施(Maps API)上时,原有的安全假设可能被悄然打破。这提醒所有平台在推出 AI 功能时需要全面审计已有的权限模型。

4. AI 产品的真正挑战是日常使用场景而非技术能力

Evans 的洞察一针见血:模型能力的天花板不断提高,但用户的日常使用频率并未同步增长。这说明 AI 产品需要从”技术演示”转向”日常习惯养成”,而这恰恰是最难的部分。

5. 开源与公开知识成为 AI 时代的战略资产

Willison 的实践表明,将代码和解决方案公开发布(博客、GitHub、工具站点)不是简单的”分享”,而是在建设一个可被代理检索和复用的知识网络。在代理时代,公开知识的边际价值被大幅放大。


值得关注的链接与资源

资源类型说明
tools.simonwillison.net工具集Willison 的 LLM 辅助 HTML 工具集合,单页应用解决特定问题
simonw/researchGitHub 仓库编程代理研究项目,包含可运行代码和报告
Agentic Engineering Patterns 系列指南Willison 的代理工程模式系列文章
Tesseract.js开源库浏览器端 OCR 引擎的 WebAssembly 实现
PDF.js开源库Mozilla 的浏览器端 PDF 渲染库
Truffle Security 报告安全研究发现 Google API 密钥权限提升漏洞的安全公司
Benedict Evans: How will OpenAI compete?分析文章Evans 对 OpenAI 商业模式和竞争策略的深度分析
Andrej Karpathy 推文社交媒体Karpathy 关于编程代理颠覆性变化的原始推文
展开正文

Simon Willison 博客 2026-02-26 中文逐字稿

原文来源:simonwillison.net | 翻译日期:2026-02-27


篇一:囤积你知道怎么做的事情

原文标题:Hoard Things You Know How to Do 原文链接:https://simonwillison.net/guides/agentic-engineering-patterns/hoard-things-you-know-how-to-do/ 发布日期:2026年2月26日 标签:coding-agents, ai-assisted-programming, generative-ai, agentic-engineering, ai, llms

我关于如何高效使用编程代理的许多建议,其实是我在没有编程代理时就觉得很有用的职业经验的延伸。这里就有一个很好的例子:囤积你知道怎么做的事情

软件开发这门技艺的很大一部分,在于理解什么是可能的、什么是不可能的,以及对如何实现这些事情至少有一个大致的概念。

这些问题可以是很宽泛的,也可以是相当冷门的。一个网页能不能仅用 JavaScript 来运行 OCR 操作?一个 iPhone 应用能不能在不运行的时候与蓝牙设备配对?我们能不能在 Python 中处理一个 100GB 的 JSON 文件而不必把整个文件加载到内存中?

你掌握的这类问题的答案越多,你就越有可能发现利用技术解决问题的机会——而且这些方式可能是其他人尚未想到的。

知道某件事在理论上是可能的,和亲眼见过它被实现是不一样的。作为软件专业人士,一个关键的资产是积累大量这类问题的答案,最好是配有可运行代码的示例。

我通过多种方式囤积这类解决方案。我的博客和 TIL(Today I Learned,今日所学)博客里塞满了我摸索出来的各种方法笔记。我有超过一千个 GitHub 仓库,收集了我为不同项目编写的代码,其中许多是演示某个关键思路的小型概念验证项目。

最近,我还利用大语言模型来帮助扩展我的代码解决方案集合,去解决更多有趣的问题。

tools.simonwillison.net 是我最大的 LLM 辅助工具和原型集合。我用它来收集我所说的 HTML 工具——单个 HTML 页面,嵌入了 JavaScript 和 CSS,解决一个特定的问题。

我的 simonw/research 仓库里有更大、更复杂的示例,在那里我挑战编程代理去研究一个问题,然后带回可运行的代码和一份详细说明发现的书面报告。

从你的囤积中重新组合

为什么要收集所有这些东西?除了帮助你构建和扩展自己的能力之外,你在这个过程中产生的资产会成为你的编程代理极其强大的输入。

我最喜欢的提示模式之一,就是告诉代理通过组合两个或更多现有的可运行示例来构建新的东西。

有一个项目帮助我深刻认识到这种方式有多高效——那就是我添加到工具集合中的第一个项目:一个基于浏览器的 OCR 工具,更详细的描述在这里。

我想要一个简单的、基于浏览器的工具,用于对 PDF 文件的页面进行 OCR——特别是那些完全由扫描图像组成、根本没有文本版本的 PDF。

我之前曾经试验过在浏览器中运行 Tesseract.js OCR 库,发现它非常能干。这个库提供了成熟的 Tesseract OCR 引擎的 WebAssembly 构建版本,让你可以从 JavaScript 调用它来从图像中提取文本。

但我不想处理图像,我想处理 PDF。然后我想起来,我之前也用过 Mozilla 的 PDF.js 库,它的功能之一就是可以把 PDF 的单个页面渲染成图像。

我的笔记中有这两个库的 JavaScript 代码片段。

以下是我输入模型的完整提示(当时用的是 Claude 3 Opus),将我的两个示例结合在一起,并描述了我想要的解决方案:

这段代码展示了如何打开一个 PDF 并将其转换为每页一张图片:

<!DOCTYPE html>
<html>
<head>
  <title>PDF to Images</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.min.js"></script>
  <style>
    .image-container img { margin-bottom: 10px; }
    .image-container p { margin: 0; font-size: 14px; color: #888; }
  </style>
</head>
<body>
  <input type="file" id="fileInput" accept=".pdf" />
  <div class="image-container"></div>
  <script>
  const desiredWidth = 800;
  const fileInput = document.getElementById('fileInput');
  const imageContainer = document.querySelector('.image-container');
  fileInput.addEventListener('change', handleFileUpload);
  pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.worker.min.js';
  async function handleFileUpload(event) {
    const file = event.target.files[0];
    const imageIterator = convertPDFToImages(file);
    for await (const { imageURL, size } of imageIterator) {
      const imgElement = document.createElement('img');
      imgElement.src = imageURL;
      imageContainer.appendChild(imgElement);
      const sizeElement = document.createElement('p');
      sizeElement.textContent = `Size: ${formatSize(size)}`;
      imageContainer.appendChild(sizeElement);
    }
  }
  async function* convertPDFToImages(file) {
    try {
      const pdf = await pdfjsLib.getDocument(URL.createObjectURL(file)).promise;
      const numPages = pdf.numPages;
      for (let i = 1; i <= numPages; i++) {
        const page = await pdf.getPage(i);
        const viewport = page.getViewport({ scale: 1 });
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        canvas.width = desiredWidth;
        canvas.height = (desiredWidth / viewport.width) * viewport.height;
        const renderContext = {
          canvasContext: context,
          viewport: page.getViewport({ scale: desiredWidth / viewport.width }),
        };
        await page.render(renderContext).promise;
        const imageURL = canvas.toDataURL('image/jpeg', 0.8);
        const size = calculateSize(imageURL);
        yield { imageURL, size };
      }
    } catch (error) {
      console.error('Error:', error);
    }
  }
  function calculateSize(imageURL) {
    const base64Length = imageURL.length - 'data:image/jpeg;base64,'.length;
    const sizeInBytes = Math.ceil(base64Length * 0.75);
    return sizeInBytes;
  }
  function formatSize(size) {
    const sizeInKB = (size / 1024).toFixed(2);
    return `${sizeInKB} KB`;
  }
  </script>
</body>
</html>

这段代码展示了如何对图像进行 OCR:

async function ocrMissingAltText() {
    var s = document.createElement("script");
    s.src = "https://unpkg.com/tesseract.js@v2.1.0/dist/tesseract.min.js";
    document.head.appendChild(s);
    s.onload = async () => {
      const images = document.getElementsByTagName("img");
      const worker = Tesseract.createWorker();
      await worker.load();
      await worker.loadLanguage("eng");
      await worker.initialize("eng");
      ocrButton.innerText = "Running OCR...";
      for (const img of images) {
        const altTextarea = img.parentNode.querySelector(".textarea-alt");
        if (altTextarea.value === "") {
          const imageUrl = img.src;
          var { data: { text } } = await worker.recognize(imageUrl);
          altTextarea.value = text;
          progressBar.value += 1;
        }
      }
      await worker.terminate();
      ocrButton.innerText = "OCR complete";
    };
  }

利用这些示例,组合成一个单独的 HTML 页面,嵌入 HTML、CSS 和 JavaScript,提供一个大的正方形区域,用户可以将 PDF 文件拖放到上面,然后 PDF 的每一页都会被转换为 JPEG 并显示在页面下方,接着使用 Tesseract 进行 OCR,结果显示在每张图片下方的文本框中。

这完美地运作了!模型输出了一个概念验证页面,完全实现了我需要的功能。

后来我又和它来回迭代了几次才得到最终结果,但整个过程只花了几分钟就构建了一个真正有用的工具,从那以后我一直在受益。

编程代理让这一切更加强大

我在 2024 年 3 月构建了那个 OCR 示例,距离 Claude Code 的首次发布还有将近一年。编程代理让囤积可运行示例变得更加有价值。

如果你的编程代理可以访问互联网,你可以告诉它做这样的事情:

使用 curl 获取 https://tools.simonwillison.net/ocrhttps://tools.simonwillison.net/gemini-bbox 的源代码,构建一个新工具,让你可以从 PDF 中选择一页并传递给 Gemini,让它返回该页面上插图的边界框。

(我在那里指定了 curl,因为 Claude Code 默认使用 WebFetch 工具,它会总结页面内容而不是返回原始 HTML。)

编程代理非常擅长搜索,这意味着你可以在自己的机器上运行它们,告诉它们在哪里可以找到你想让它们执行的操作示例:

~/dev/ecosystem/datasette-oauth 项目添加模拟 HTTP 测试,灵感来自 ~/dev/ecosystem/llm-mistral 中的做法。

通常这就足够了——代理会启动一个搜索子代理来调查,并只拉回它完成任务所需的细节。

由于我的大量研究代码都是公开的,我经常告诉编程代理克隆我的仓库到 /tmp,然后将它们作为输入使用:

从 GitHub 克隆 simonw/research/tmp,找到将 Rust 编译为 WebAssembly 的示例,然后用它为这个项目构建一个演示 HTML 页面。

这里的核心思想是,编程代理意味着我们只需要弄清楚一个有用的技巧一次。如果这个技巧随后被记录在某个地方,并附有可运行的代码示例,我们的代理就可以参考该示例,并用它来解决未来任何类似形状的项目。


篇二:引用 Andrej Karpathy

原文标题:A quote from Andrej Karpathy 原文链接:https://simonwillison.net/2026/Feb/26/andrej-karpathy/ 发布日期:2026年2月26日 标签:ai, andrej-karpathy, generative-ai, llms, ai-assisted-programming, coding-agents, agentic-engineering

Andrej Karpathy 说道:

“很难传达 AI 在最近两个月内让编程发生了多大的变化:不是以’一切照常的进步’那种渐进方式随着时间推移的变化,而是具体就在去年 12 月。虽然有一些附加条件,但在我看来,编程代理在 12 月之前基本不能用,12 月之后基本能用了——模型的质量、长期连贯性和韧性有了显著提升,它们能够坚持完成大型和长期的任务,足以对默认的编程工作流程产生极大的颠覆性影响。”

——Andrej Karpathy


篇三:Google API 密钥本不是秘密,但 Gemini 改变了规则

原文标题:Google API Keys Weren’t Secrets. But then Gemini Changed the Rules 原文链接:https://simonwillison.net/2026/Feb/26/google-api-keys/ 发布日期:2026年2月26日

Simon Willison 报道了 Truffle Security 发现的一个重大安全问题:原本设计为可公开使用的 Google API 密钥,在 Gemini API 启用后变得危险了。

核心问题

这个问题的本质是一个权限提升序列。开发者历史上将 Google Maps API 密钥直接嵌入网站——因为这些密钥就是被设计为公共标识符的。然而,当 Google 在相同的项目上启用了 Gemini API 时,那些相同的密钥获得了访问敏感端点和计费服务的权限——而开发者没有收到任何通知。

正如文章所解释的:「让这成为权限提升而非配置错误的,是事件发生的顺序。」开发者创建了用于 Maps 的公共 API 密钥,Gemini API 随后在这些项目上被启用,然而「开发者从未被警告过密钥的权限在其不知情的情况下发生了变化。」

问题规模

Truffle Security 在 2025 年 11 月的 Common Crawl 数据中发现了 2,863 个暴露的 API 密钥,这些密钥能够访问 Gemini。值得注意的是,其中一些属于 Google 自己,有一个从 2023 年 2 月就已部署——比 Gemini API 早了好几年。

建议

Google 正在努力撤销受影响的密钥,但用户应该验证自己的 API 密钥是否受到这种漏洞的影响。


篇四:引用 Benedict Evans

原文标题:A quote from Benedict Evans 原文链接:https://simonwillison.net/2026/Feb/26/benedict-evans/ 发布日期:2026年2月26日 标签:ai, openai, chatgpt, benedict-evans

Benedict Evans 说道:

“如果人们最多每周只使用这个东西几次,而且在普通的日子里想不出用它做什么,那它就没有改变他们的生活。OpenAI 自己也承认这个问题,谈到模型能做什么和人们实际用它们做什么之间存在一个’能力差距’,在我看来,这是一种回避说出你没有清晰的产品市场契合度的方式。因此,OpenAI 的广告项目一方面只是为了覆盖服务那 90% 或更多不付费用户的成本(并在广告商中获得早期优势,以及在这可能如何运作方面积累早期学习经验),但更具战略意义的是,它也是为了让给那些用户提供最新、最强大(即最昂贵的)模型成为可能,希望这能加深他们的参与度。”

——Benedict Evans,摘自《OpenAI 将如何竞争?》(How will OpenAI compete?)