跳到正文
Simon Willison·· 9 天前AI 评分34

Simon Willison 用 Codex 语音模式为博客新增 Newsletters 页面

A new feature for my blog, built using my voice

AI 导读

Simon Willison 用 ChatGPT 桌面版 Codex 标签页的语音对话模式,在做饭的半小时里几乎全程靠说话为博客建好了 Newsletters 页面,底层模型是 GPT-6 Astra High。

正文 · AI 翻译

2026年10月9日

我今天为我的博客发布了一个新功能:Newsletters 页面,它提供了我发出的所有新闻通讯的索引,包括我免费的每周 Substack 和每月仅限赞助者的更新。我几乎完全是用语音构建这个功能的,一边做晚饭一边对着笔记本电脑聊天。

Codex 语音模式

我为此使用了 ChatGPT 桌面应用,在 Codex 标签页中,使用语音对话模式,针对本地开发环境运行。它看起来是这样的:

Three columns of the ChatGPT app. The left hand column shows my recent conversations. The middle column is a transcript of the conversation, with a throbbing black blob representing voice mode. The right hand column shows a local dev server version of my blog, with the Newsletters page visible.

我通过输入以下内容,针对本地 simonwillisonblog 检出启动了会话:

Start dev server and open in browser

这让我预览了它将处理的网站,也意味着我之后可以要求它向我展示新页面,以便直观地跟踪它的进展。

然后我点击了“开始新的语音聊天”按钮——那不是麦克风按钮,而是它右边的那个——并把笔记本电脑放在厨房里,这样我做饭时就能和它说话。

与我的电脑交谈

我很清楚自己想要构建什么,而且这是一个足够简单的 Django 功能,我确信模型(在这种情况下是 GPT-6 Astra High)能够做到。一个新模型、一次迁移、一些视图代码、模板,以及几个从外部来源填充数据库的导入函数。

以下是 Codex 捕获的我的语音转录摘录:

嗯,它们不会。嗯,这将是一种新的内容类型。嗯,它不会显示……哦,等等。对,不——我不希望它显示在我的,嗯,标签页面和日期归档页面中,还有……其实,不,我想……我不希望它出现在标签页面上。我不希望它出现在,嗯,博客索引页面上。但我想我确实希望它出现在基于日期的页面上。你知道,如果你导航到9月19日,而我在那天发送了一份新闻通讯,我希望它显示出来。所以……这是——所以我想我们可能需要一个新模型。另一件事是我希望它们可搜索,呃,Substack 的那些不可搜索,因为那些实际上只是我博客上其他内容的副本。这些每月的内容确实包含独特的内容,而且一旦它们……发布,比如在发出一个月后公开,我希望它们出现在我的搜索结果中。

显然这已经足够清楚,模型知道我想要构建什么!你可以阅读完整的转录,包括所有不流畅之处,在这个 Gist 中。

我们就这样继续了大约半小时(做晚饭所需的时间)。模型会回复,偶尔问一些澄清性问题,然后开始修改代码。

我们构建了什么

我们完全通过语音取得了令人惊讶的进展:

  • 在 Django 中表示导入的新闻通讯的新模型和迁移,以及相应的 Django Admin 配置
  • Four working imports:
    • 通过 RSS 获取最新的 Substack 条目
    • 通过它们未公开的 API 获取其他所有 Substack 条目,GPT-6 Astra 要么知道这个 API,要么通过搜索找到了它
    • 来自我的 simonw/monthly-newsletter-archive GitHub 仓库的所有已发布每月新闻通讯
    • 来自一个私有仓库的我最近的仅限赞助者的私密新闻通讯
  • /newsletters/ 和 /newsletters/2026/ 公开归档页面
  • 新闻通讯也显示在日和月归档页面上,但不显示在标签页面或我的主页上
  • 每周 Substack 新闻通讯链接到 Substack;归档的每月新闻通讯有自己的页面
  • 与我的网站搜索引擎集成

它几乎可以发布了。问题出在导入上:Astra 提出可以从我的本地副本导出数据,这样我就能把它导入到生产环境,但我希望它能像我的其他导入脚本一样工作。由于部分数据存放在一个私有的 GitHub 仓库中,这需要创建一个新的 API 密钥,而我知道为此我得在键盘前坐上一会儿。

通过审查来完成它

当我做完饭并判断它基本功能完备后,我让 Codex 创建了一个分支并打开了一个拉取请求。

我在 GitHub 的 PR 界面中审查了代码。它几乎就是我需要的,只是其中一个导入脚本它选择了在子进程中使用 Git。我需要其中一个导入从私有 Git 仓库拉取,所以我认为用 API 会更好。我切换回打字,让 Codex 把它换成基于 API 的导入。

你可以在PR 上的额外提交中看到我在审查期间所做的更改。我修复了导入机制,并对那些公开页面的显示做了几处调整。又花了半小时基于打字的提示,才达到我满意、可以通过合并 PR 将其部署到生产环境的状态。

最终结果

你可以在新的新闻通讯索引页面看到最终结果,或者查看往期月度新闻通讯的页面。

Newsletters page. It shows two Substack posts (with thumbnails) and one LLM digest Sponsors-only newsletter with a list of headings. On the right is a CTA to subscribe to my Substack and another one for my $10/month monthly briefing newsletter.

索引页面将我最近的 Substack 每周新闻通讯和 GitHub 赞助者月度新闻通讯按时间倒序混排在一起。页面往下是按年份归档页面的链接。

GPT-6 Astra 设计了该页面,然后根据我在厨房里瞥一眼本地预览时给出的口头反馈对设计做了调整。

更适合多任务处理,而非日常主力

OpenAI 喜欢在像 DevDay 这样的场合使用这种语音驱动的演示——而且它们在那样的环境中确实效果很好。不过我认为这不会成为我的日常主力。

我之前写过,我在遛狗时用手机上的 ChatGPT 语音模式完成了多少“工作”——主要是研究和头脑风暴,但偶尔也会通过让 ChatGPT 编写和测试代码片段来做实际的开发工作。

这次感觉不同。加入了可视化预览,再加上当我需要传达某些用语音说不清楚的内容时可以通过键盘输入或粘贴,这让它成为与编码智能体交互的一种强大得多的方式。

不过一旦深入到细节,我还是会切换回打字。能够粘贴示例和错误信息,或者直接高亮需要更改的代码或功能,仍然比试图用语言描述更高效。

我主要在家工作,这很好,因为在共享办公空间里我绝不想这样跟我的电脑说话!

对我来说最杀手级的功能是多任务处理能力。我通常一边做饭一边放着播客或 TikTok;现在我可以真正地做点东西了。

来源:Simon Willison · simonwillison.net