0%

在近期的 AI 辅助开发实践中,我逐步形成了一套相对稳定、可复用的工作流,核心目标是:让 AI 可规划、可执行、可追踪、可审查

整体流程如下:

首先,为每个项目建立专属的 agents.md,用于描述项目背景、技术约束以及 AI 开发规范,例如强制要求在代码生成后执行静态检查和单元测试。这一步相当于为 AI 提供“项目宪法”。

其次,提出足够明确、结构化的需求,并使用 Copilot 的 Planning 模式生成开发计划,避免直接进入无序实现。

在实施阶段,切换至 Copilot 的 Agent 模式执行计划,并明确要求使用 PRD.mdprocess.md 跟踪进度:前者记录需求,后者记录每次代码变更与当前状态。通过外部文件系统作为长期记忆,降低上下文丢失的风险。

完成初步实现后,由人工对功能正确性进行验证,确保需求被真实满足,而非“看起来能跑”。

最后,引入我自定义的Linus 风格 Code Review Agent进行代码审查,集中指出设计、可维护性和工程质量问题,再由人工或 AI 执行针对性的重构。

值得一提的是,近期社区中出现了一个名为 planning-with-files 的 Claude Skill,其思路与上述流程高度相似,同样通过外部文件作为 AI 的长期记忆,并额外引入 findings.md 用于沉淀调研结论和经验知识。这类模式进一步验证了“文件即上下文”的工程价值。

1
2
# Skill安装命令
npx skills add https://github.com/othmanadi/planning-with-files --skill planning-with-files

总体来看,AI 开发正在从“对话式生成”走向“工程化协作”,而可追踪的计划、状态与知识载体,是这一转变的关键基础。

Zed 是一款由前 Atom 及 Tree-sitter 团队打造的跨平台代码编辑器。它采用 Rust 语言编写,核心定位在于极致性能、原生 AI 集成以及多人实时协作

Zed is a minimal code editor crafted for speed and collaboration with humans and AI.

得益于 Rust 语言的底层优势和自研的 GPU 加速框架 GPUI,Zed 在响应速度上远超基于 Electron 的编辑器。
在处理中等规模项目时,Zed 的内存占用通常仅为 VS Code 的十分之一左右(约 100MB vs 1GB+)。
Zed 充分利用多核 CPU 和 GPU 渲染,使得输入延迟和 UI 刷新达到了原生应用的最佳水准。

Zed集成了很多AI开发功能,包括代码智能补全、编辑预测、Agent开发模式。
除了登录账号订阅Zed官方的AI服务外,用户还可以通过BYOK模式使用自己的OpenAI、Gemini或Claude API密钥(也可以直接使用Github Copilot订阅)。
Zed也支持和Claude Code、Gemini CLI与Codex CLI集成。

虽然插件生态尚处于早期阶段,但 Zed 通过原生支持 LSP(语言服务协议),已实现对 Python、Rust、TypeScript 等主流语言的完美支持。

对于追求极致流畅度、且希望在开发流中深度使用 AI 的开发者来说,Zed 无疑是目前 VS Code 最强有力的挑战者。

【由 ChatGPT 辅助翻译】

原文链接

发布时间: 2025-12-26

uv 安装包的速度比 pip 快一个数量级。通常的解释是“它是用 Rust 写的”。这确实没错,但并不能解释太多。毕竟,也有大量用 Rust 编写的工具,并没有表现出显著的速度优势。真正有意思的问题在于:究竟是哪些设计决策带来了这种差异

Charlie Marsh 在 Jane Street 的一次演讲(Jane Street talk)以及一篇来自 Xebia 的工程深度解析(Xebia engineering deep-dive)已经很好地覆盖了技术细节。更值得关注的,是其中的设计选择:哪些标准让“快速路径”成为可能,uv 放弃了哪些 pip 所支持的特性,以及哪些优化其实完全不依赖 Rust

使 uv 成为可能的标准

pip 的缓慢并不是实现层面的失败。多年来,Python 的打包体系必须通过执行代码才能知道一个包依赖什么。

问题出在 setup.py 上。你无法在不运行 setup 脚本的情况下知道一个包的依赖;但你又无法在不先安装构建依赖的情况下运行 setup 脚本。PEP 518 在 2016 年明确指出了这一点:“你无法在不知道依赖的情况下执行 setup.py 文件,但目前又没有一种标准化的方式,可以在不执行 setup.py 文件的前提下,以自动化手段获知这些依赖。”

这种“先有鸡还是先有蛋”的问题,迫使 pip 只能采取一条低效且危险的路径:下载包、执行不受信任的代码、失败、安装缺失的构建工具、再重试。每一次安装,都可能演变成一连串子进程的启动和任意代码的执行。安装一个源码分发包,本质上就像是多了几步的 curl | bash

解决方案是分阶段出现的:

  • PEP 518(2016)引入了 pyproject.toml,为包提供了一个无需执行代码即可声明构建依赖的位置。TOML 格式借鉴自 Rust 的 Cargo,这也让“一个 Rust 工具回过头来修复 Python 打包体系”这件事看起来不那么像巧合。
  • PEP 517(2017)将构建前端与后端解耦,使 pip 不再需要理解 setuptools 的内部细节。
  • PEP 621(2020)标准化了 [project] 表,使依赖信息可以通过解析 TOML 获取,而不是运行 Python 代码。
  • PEP 658(2022)将包的元数据直接放入 Simple Repository API,使解析器甚至无需下载 wheel 就能获取依赖信息。

PEP 658 于 2023 年 5 月 在 PyPI 上正式上线;uv 则在 2024 年 2 月 发布。uv 之所以能够如此之快,是因为整个生态系统终于具备了支撑这种速度的基础设施。像 uv 这样的工具在 2020 年是不可能发布的——当时这些标准还不存在。

其他生态系统更早就解决了这个问题。Cargo 从一开始就拥有静态元数据;npm 的 package.json 是声明式的。Python 的打包标准,直到最近才终于在这一点上追平了它们。

uv 放弃了什么

速度来自于删减。你不需要走的每一条代码路径,都是你不必等待的时间。

uv 的兼容性文档本质上就是一份“它不做什么”的清单:

不支持 .egg
Egg 是早于 wheel 的二进制分发格式。pip 仍然要处理它们;uv 则干脆完全不支持。这个格式早在十多年前就已经过时了。

不支持 pip.conf
uv 完全忽略 pip 的配置文件:不解析、不读取环境变量、不从系统级或用户级位置继承配置。

默认不进行字节码编译。
pip 在安装时会将 .py 文件编译为 .pyc。uv 跳过了这一步,从而为每次安装节省时间。如果你需要,也可以显式开启。

强制使用虚拟环境。
pip 默认允许直接安装到系统 Python。uv 则反其道而行,在没有显式标志的情况下拒绝修改系统 Python。这消除了一整类权限检查和安全相关的代码。

更严格地执行规范。
pip 会接受一些在技术上违反打包规范的畸形包;uv 会直接拒绝。容忍度越低,回退逻辑就越少。

忽略 requires-python 的上界。
当一个包声明需要 python<4.0 时,uv 会忽略这个上界,只检查下界。这极大地减少了解析器的回溯,因为这些上界几乎总是错误的。包作者声明 python<4.0,通常只是因为还没在 Python 4 上测试过,而不是因为真的会出问题。这种约束是防御性的,而非预测性的。

默认“第一个索引即胜出”。
当配置了多个包索引时,pip 会逐一检查所有索引;uv 则在第一个找到该包的索引处立即停止。这既可以防止依赖混淆攻击,也避免了多余的网络请求。

上述每一项,都是 pip 必须执行而 uv 不需要执行的一条代码路径。

在这里,Rust 才真正发挥作用

有些优化确实必须依赖 Rust 才能实现:

零拷贝反序列化。
uv 使用 rkyv 对缓存数据进行反序列化,而无需复制数据。其数据格式本身就是内存中的表示形式。其他语言中也有类似 FlatBuffers 这样的库可以做到这一点,但 rkyv 与 Rust 的类型系统深度集成。1

线程级并行。
Python 的 GIL 迫使并行工作只能通过多进程来完成,这会带来进程间通信的开销以及数据复制。Rust 可以在原生线程之间并行执行,并共享内存而无需序列化边界。这在依赖解析阶段尤为重要,因为求解器需要探索大量版本组合。1

没有解释器启动成本。
pip 每次启动子进程,都要付出 Python 解释器启动的代价;而 uv 是一个单一的静态二进制文件,没有需要初始化的运行时。

紧凑的版本表示。
在可能的情况下,uv 会将版本号打包为 u64 整数,使比较和哈希操作非常高效。超过 90% 的版本号都能放入一个 u64 中。这是一种微优化,但在数百万次比较中会不断累积效果。

这些都是实实在在的优势。但与放弃遗留支持、并充分利用现代标准所带来的架构层收益相比,它们反而显得次要一些。

设计优先于语言

uv 之所以快,并不是因为它用什么语言写成,而是因为它选择了不做什么。PEP 518、517、621 和 658 所推动的标准化工作,使得高速的包管理成为可能;而放弃 egg、pip.conf 以及宽松(但复杂)的解析策略,则让这种速度真正落地。Rust 只是让它在此基础上又快了一点。

从技术上讲,pip 明天就可以实现并行下载、全局缓存,以及仅基于元数据的依赖解析。但它并没有这样做,主要原因在于:对过去十五年各种边缘情况的向后兼容性,始终优先于激进的重构。这也意味着,pip 注定会比那些在现代假设之上重新出发的工具更慢。

其他包管理器可以从中学到的经验是:使用静态元数据;在发现依赖时避免执行代码;在下载之前就一次性完成完整的依赖解析。Cargo 和 npm 多年来一直以这种方式运作。如果你的生态系统必须运行任意代码才能知道一个包需要什么,那你在设计层面上就已经输了。

前段时间突发奇想,从更理论的角度审视AI智能体,于是和Gemini进行了一番对话。

我的提问是:从系统论、控制论、信息论的视角,深度探讨AI智能体

以下是Gemini的回答:

这是一个非常深刻且宏大的视角。系统论(Systems Theory)、控制论(Cybernetics)和信息论(Information Theory),也就是经典的“老三论”(SCI),是研究复杂系统的基石。

将AI智能体(AI Agent)置于这三个维度下审视,我们不再将其视为单纯的代码或大模型,而是一个 “在开放环境中,通过信息交互维持自身有序性,并利用反馈机制实现目标的复杂系统”

以下是基于这三个维度的深度探讨:


一、 系统论视角:智能体的解剖与涌现

核心隐喻:AI Agent 是一个开放的有机整体,而非孤立的算法。

在系统论看来,整体大于部分之和。AI Agent 不是单纯的大语言模型(LLM),LLM 只是它的“大脑”。Agent 是一个由多个组件构成的功能系统。

1. 结构功能主义:从 LLM 到 Agent 的系统架构

一个典型的 AI Agent 系统架构(如 AutoGPT 或 LangChain 架构)完全符合系统论的定义:

  • 要素(Elements):
    • 中枢(LLM): 负责推理、规划和决策。

    • 感知(Perception): 多模态输入(文本、视觉、音频)。

    • 记忆(Memory): 短期记忆(Context Window)和长期记忆(Vector Database)。

    • 行动(Tools/Action): API调用、搜索、代码执行。

    • 结构(Structure): 这些要素通过特定的 Prompt Engineering 和 Orchestration(编排)逻辑连接,形成“感知-规划-行动-观察”的链条。

2. 开放系统与环境交互

系统论强调系统与环境的边界。传统的机器学习模型是封闭的(输入->输出),而 AI Agent 是开放系统(Open System)

  • Agent 必须存在于一个“环境”中(操作系统、浏览器、游戏世界)。
  • 它通过输入输出接口与环境进行物质(数据)和能量(算力)的交换,从而改变环境状态。

3. 涌现性(Emergence):多智能体系统

当多个 AI Agent 协作时(如斯坦福的虚拟小镇实验),单个 Agent 的简单规则(“我要去买咖啡”)在系统层面涌现出了复杂的社会行为(选举、派对、谣言传播)。这是系统论中 “涌现” 的经典体现——宏观智能来自于微观交互。

系统论洞见: AI Agent 的核心竞争力不在于模型参数有多大(部分),而在于其组件(记忆、工具、规划)如何通过架构设计形成高效的整体协同


二、 控制论视角:目标、反馈与自适应

核心隐喻:AI Agent 是一个拥有“目的”并能自我修正的舵手。

控制论的核心是反馈(Feedback)控制(Control)。在这一视角下,AI Agent 被视为一个目的论系统(Teleological System),即它的行为是为了达成某种特定的目标状态。

1. 负反馈调节:从错误中修正

这是 Agent 与 Chatbot 的本质区别。

  • 开环系统(Chatbot): 用户提问 -> 模型回答。结束。
  • 闭环系统(Agent): 设定目标(“帮我订票”) -> 行动 -> 观察结果(Feedback) -> 结果不符 -> 修正行动 -> 再次尝试 -> 达成目标。
  • 这种**OODA循环(Observe-Orient-Decide-Act)**是控制论在 AI Agent 中的直接投射。Agent 通过不断的负反馈(误差修正)来逼近目标。

2. 黑箱与白箱控制

  • LLM 本身在很大程度上是一个黑箱(Black Box),我们难以解释其内部具体的神经元触发路径。
  • 但 AI Agent 的架构设计试图在黑箱之外构建白箱控制逻辑(White Box Logic)。例如,通过 Chain-of-Thought (CoT) 强制模型输出中间步骤,或者通过 ReAct (Reasoning + Acting) 框架,让思维过程显性化,从而变得可控。

3. 稳态与失控

控制论关注系统的稳定性。

  • 稳态(Homeostasis): Agent 需要在长对话或复杂任务中保持“人设”或“目标”不漂移。
  • 正反馈导致崩溃: 幻觉(Hallucination)往往是一种正反馈循环。模型生成了一个错误,后续的推理基于这个错误继续生成,导致误差放大,最终系统失控。优秀的 Agent 架构必须包含“看门狗”机制来切断这种正反馈。

控制论洞见: AI Agent 的强大在于其鲁棒性。一个好的 Agent 不是因为它从不犯错,而是因为它拥有强大的反馈回路,能够检测并修正错误。


三、 信息论视角:熵减与不确定性消除

核心隐喻:AI Agent 是通过处理信息来对抗无序(熵)的机器。

香农的信息论关注信息的量化、传输和处理。在这一视角下,AI Agent 的本质是信息处理器,其终极目标是负熵(Negative Entropy)——即在混乱的环境中建立秩序。

1. 消除不确定性(Uncertainty Reduction)

  • 用户的任务通常是模糊的(高熵)。
  • Agent 的工作流就是通过多轮交互、搜索确认、推理,不断排除可能性的过程,将高熵的模糊指令转化为低熵的确切行动(如具体的 API 调用参数)。
  • 公式化理解:Agent 的价值等于其消除的**信息熵(Information Entropy)**总量:

Agent 通过观察(获取信息)改变概率分布 ,使系统确定性增加。

2. 信道容量与压缩

  • 上下文窗口(Context Window): 这是 Agent 的信道容量(Channel Capacity)限制。Agent 必须学会“有损压缩”,将长期记忆中的关键信息提取摘要,放入有限的 Context Window 中。
  • Prompt Engineering: 从信息论角度看,Prompt 是对任务信息的编码(Encoding),而 LLM 的输出是解码(Decoding)。优秀的 Prompt 设计就是为了最大化信噪比(Signal-to-Noise Ratio),减少模型对噪声的误解。

3. 幻觉作为“噪声”

在通信模型中,幻觉可以被视为信道中的噪声(Noise)

  • 当模型内部知识不足(数据缺失)或上下文过长(信号衰减)时,噪声占比上升,Agent 就会开始“一本正经地胡说八道”。
  • RAG(检索增强生成)技术的本质,就是引入外部高保真信源,以提高输入端的信噪比。

信息论洞见: AI Agent 的瓶颈往往在于带宽(记忆检索的效率、上下文长度)和信噪比。提升 Agent 能力的关键在于更高效的信息编码和更精准的噪声过滤。


四、 综合图谱:三论合一的 AI Agent

我们可以用一个综合模型来概括这三个视角:

视角 关注点 AI Agent 中的体现 关键挑战
系统论 整体与关系 记忆+规划+工具的编排;多智能体协作 如何避免组件间的割裂?如何实现涌现?
控制论 行为与反馈 ReAct 模式;自我反思(Self-Reflection);错误修正 如何防止死循环?如何保证目标不漂移?
信息论 数据与熵 Context 管理;RAG;Prompt 编码 如何在有限窗口处理无限信息?如何抑制幻觉噪声?

总结

从“老三论”的视角来看,AI智能体是人类试图创造的一种“数字生命体”雏形

  1. 它以系统的形式存在,具备结构完整性;
  2. 它通过控制回路与环境交互,表现出目的性;
  3. 它以信息处理为能量,通过降低熵值来产出价值。

这种视角超越了单纯的代码工程,它告诉我们:要构建更强大的 AGI(通用人工智能),我们不能只盯着改进 Transformer 的算法(微观优化),更需要设计优良的反馈系统(控制论)高效的信息流转架构(系统论)

VS Code 的 Github Copilot 拓展最近的更新带来了对 Claude Skills 的实验性支持,我简单尝试了一下,使用 Claude 官方的前端设计 Skill开发了一个赛博朋克风格的个人网站。 项目初始化和代码编辑全程由 AI 自动完成,我只是手工批准了一些关键步骤。
仓库地址
感言:AI生成的网页终于不是千篇一律的渐变紫背景了。

附 Frotend Design Skill 的 skill.md:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
---
name: frontend-design
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
license: Complete terms in LICENSE.txt
---

This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.

The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.

## Design Thinking

Before coding, understand the context and commit to a BOLD aesthetic direction:

- **Purpose**: What problem does this interface solve? Who uses it?
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
- **Constraints**: Technical requirements (framework, performance, accessibility).
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?

**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.

Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:

- Production-grade and functional
- Visually striking and memorable
- Cohesive with a clear aesthetic point-of-view
- Meticulously refined in every detail

## Frontend Aesthetics Guidelines

Focus on:

- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.

NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.

Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.

**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.

Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.

【由 ChatGPT 辅助翻译】

来源 URLhttps://addyo.substack.com/p/my-llm-coding-workflow-going-into
发布时间:2025-12-18T15:30:46+00:00


AI 编码助手在今年成为了颠覆性的工具,但要真正发挥它们的威力,需要技巧与结构化的方法。 这些工具显著提升了 LLM 在真实世界编码中的能力,许多开发者(包括我自己)都积极拥抱了它们。

以 Anthropic 为例,工程师对 Claude Code 的采用程度之高,以至于 今天 Claude Code 约 90% 的代码是由 Claude Code 自己编写的。然而,将 LLM 用于编程并不是一键魔法式的体验——它“困难且不直观”,要获得优秀的结果需要学习新的模式。批判性思维依然至关重要。经过一年多的项目实践,我逐渐收敛出一种与许多资深开发者相似的工作流:把 LLM 当作一个强大的结对程序员,而不是具备自主判断力的实体——它需要清晰的指令、充分的上下文以及持续的监督

在本文中,我将分享我在迈向 2026 时如何规划、编码并与 AI 协作,总结我个人经验以及社区集体学习中沉淀下来的技巧与最佳实践。这是一种更有纪律性的 “AI 辅助工程(AI-assisted engineering)” 方法——在积极利用 AI 的同时,依然自豪地对最终产出的软件负责

如果你对我更多的工作流细节感兴趣,可以参考《The AI-Native Software Engineer》;若不想深入了解,我们直接进入我学到的一些经验教训。


先制定清晰的计划(先有规格说明,再写代码)

不要只是把愿望丢给 LLM ——先定义问题并规划解决方案。

一个常见的错误是,用一个含糊的提示直接让 AI 生成代码。在我的工作流(以及许多人的实践)中,第一步是与 AI 一起头脑风暴并制定一份详细的规格说明,然后在编写任何实际代码之前,先列出一个逐步的计划。对于一个新项目,我会描述想法,并让 LLM 不断向我提问,直到我们把需求和边界情况都理清。最终,我们会将这些内容整理成一份完整的 spec.md,其中包含需求、架构决策、数据模型,甚至测试策略。这份规格说明构成了开发的基础。

接下来,我会把 spec 输入给一个具备推理能力的模型,并提示它生成一份项目计划:将实现拆解为逻辑清晰、易于消化的任务或里程碑。AI 实质上是在帮助我完成一份迷你的“设计文档”或项目计划。我通常会对这份计划反复迭代——编辑它、让 AI 批评或完善——直到它足够连贯且完整。只有在这之后,我才会进入编码阶段。前期的这种投入看起来可能有些慢,但回报极高。正如 Les Orchard 在这里所说,这就像是在 “15 分钟内做一次瀑布式开发”——一个快速而结构化的规划阶段,让后续编码顺畅得多。

有了清晰的规格和计划,当我们真正释放代码生成能力时,人和 LLM 都非常清楚要构建什么、以及为什么要这么做。简而言之,先规划能迫使你和 AI 达成共识,避免无谓的反复。这一步很多人容易跳过,但经验丰富的 LLM 开发者如今已经把健壮的规格/计划视为整个工作流的基石。


将工作拆分为小而可迭代的任务块

范围管理至关重要——给 LLM 可管理的任务,而不是一次性丢整个代码库。

我学到的一个关键经验是:避免让 AI 一次性产出庞大、整体化的结果。相反,我们应该把项目拆解成迭代的小步骤或工单,并逐个完成。这本来就是良好的软件工程实践,但在 AI 参与时尤为重要。LLM 在面对聚焦的问题时表现最好:一次实现一个函数、修复一个 bug、添加一个功能。举例来说,在完成规划后,我会对代码生成模型说:“好,我们来实现计划中的第 1 步。”我们完成这一步,测试它,然后进入第 2 步,如此往复。每个块都足够小,既在模型的上下文能力范围内,也便于你理解生成的代码。

这种方式能有效防止模型“跑偏”。如果你一次性要求太多,它很容易困惑,或者生成一个 “杂乱无章的混合体”,难以梳理。有开发者反馈,当他们试图让 LLM 生成大块应用代码时,最终得到的是不一致和重复——“就像 10 个开发者各干各的,却从不沟通”。我也深有体会;解决办法就是停下来、后退一步,把问题拆成更小的部分。每一轮迭代,我们都会带着已有的上下文继续构建。这也非常契合 测试驱动开发(TDD)——我们可以在过程中为每个模块编写或生成测试(稍后会详细谈测试)。

现在已有不少编码代理工具明确支持这种分块式工作流。例如,我经常生成一个结构化的 “prompt plan” 文件,里面包含每个任务对应的一系列提示,这样 Cursor 等工具就可以按顺序逐条执行。核心原则是:避免大跨度跳跃。通过小循环迭代,我们可以显著降低灾难性错误的概率,并快速纠偏。LLM 擅长快速、受控的小任务——善用这一点。


提供充分的上下文信息和指导

LLM 的能力取决于你提供的上下文——把相关代码、文档和约束展示给它。

在处理代码库时,我会确保把 AI 所需的全部信息都提供到位,包括它需要修改或参考的代码、项目的技术约束、以及已知的坑或偏好的实现方式。现代工具在这方面有所帮助:例如,Anthropic 的 Claude 在 “Projects” 模式下可以把整个 GitHub 仓库引入上下文;Cursor 或 Copilot 这类 IDE 助手会自动把当前打开的文件加入提示。但我往往会更进一步——如果我怀疑模型并不了解某些内容,我会使用像 Context7 这样的 MCP,或者手动把关键代码或 API 文档粘贴进对话。

资深 LLM 用户非常强调这种“上下文打包(context packing)”。例如,在编码前做一次**“脑内倾倒(brain dump)”**,把模型需要知道的一切都告诉它:高层目标与不变量、优秀方案的示例、以及应当避免的做法。如果我要让 AI 实现一个棘手的方案,我可能会提前说明哪些朴素解法太慢,或者给出一个外部参考实现。如果我使用的是冷门库或全新的 API,我会直接贴上官方文档或 README,避免模型“盲飞”。所有这些前置上下文都会显著提升输出质量,因为模型不再需要猜测——它掌握了事实与约束。

现在也有一些工具可以自动化上下文打包。我尝试过 gitingestrepo2txt,它们本质上是把代码库中相关部分“导出”为一个文本文件供 LLM 阅读。在处理大型项目时,这类工具非常救命——你生成一个 output.txt,把关键源文件打包给模型即可。原则很简单:不要让 AI 在信息不完整的情况下工作。如果修一个 bug 需要理解四个模块,就把这四个模块都给它。是的,需要关注 token 限制,但当前前沿模型的上下文窗口已经相当大(数万 token)。要明智地使用它们。我通常只选择性地包含与当前任务相关的代码,并明确告诉 AI 哪些内容不在范围内(以节省 token)。

我认为 Claude Skills 很有潜力,因为它们把原本脆弱、需要反复提示的流程,变成了可持久、可复用的能力模块——将指令、脚本和领域知识打包成 Skill,当请求匹配时由工具自动应用。这比泛泛的提示更可靠、更具上下文感知能力,也让我们从一次性互动,转向把可重复流程和团队知识编码进工作流中。社区里已经有不少整理好的 Skills 集合;我最喜欢的例子之一是 frontend-design skill,它可以“终结”LLM 生成 UI 中常见的紫色审美。在更多工具原生支持 Skills 之前,也有一些变通方案

最后,在提示中用注释和规则来引导 AI。我可能会在代码片段前写:“这是 X 的当前实现,我们需要扩展它以支持 Y,但要注意不要破坏 Z。”这些小提示非常有用。LLM 是字面主义者——它们会遵循指令,所以请给出详细、有上下文的说明。通过主动提供上下文和指导,我们可以最大限度减少幻觉和跑题建议,得到真正契合项目需求的代码。

选择合适的模型(必要时同时使用多个模型)

并非所有编码型 LLM 都是一样的——有意识地选择工具,并且不要害怕在过程中切换模型。

在 2025 年,我们已经拥有了多种能力强大的、面向代码的 LLM。我的工作流中有一项重要内容是:为不同任务选择最合适的模型或服务。有时,甚至同时让两个或更多 LLM 并行尝试同一个问题、交叉对比它们的思路,也非常有价值。

每个模型都有自己的“性格”。关键在于:如果某个模型卡住了,或者给出的结果平庸,就换一个试试。 我确实经常把同一个提示,从一个聊天窗口原封不动地复制到另一个服务中,看是否能得到更好的处理结果。这种“模型换座位(model musical chairs)”的做法,在你撞上某个模型的盲区时,往往能救场。

同时,务必确保你使用的是当前最好的版本。如果条件允许,就用最新的 “pro” 级模型——质量真的很重要。是的,这通常意味着要付费,但生产力的提升往往值得。归根结底,选择那个与你**“合拍”**的 AI 结对程序员。我认识一些人更偏好某个模型,仅仅是因为他们喜欢那个模型回答问题的“感觉”。这完全合理——当你几乎是在与 AI 持续对话时,交互体验和语气本身就会产生影响。

就我个人而言,最近我在很多编码工作中更偏向使用 Gemini,因为它的交互感觉更自然,而且往往一次就能理解我的需求。但如果需要,我会毫不犹豫地切换到其他模型;有时,第二个意见能让解决方案浮现出来。总结来说:为任务选择最合适的工具,并记住——你手中拥有一整套 AI 武器库。


在整个软件生命周期中充分利用 AI 编码能力

在整个 SDLC 中使用面向编码的 AI,全面强化你的工作流。

在命令行层面,新的 AI 代理已经出现。Claude Code、OpenAI 的 Codex CLI,以及 Google 的 Gemini CLI,都是可以直接在项目目录中对话的 CLI 工具——它们可以读取文件、运行测试,甚至执行多步骤修复。我也用过 Google 的 Jules 和 GitHub 的 Copilot Agent——这些是异步编码代理,它们会在云端 VM 中克隆你的仓库,在后台完成任务(编写测试、修复 bug),然后为你提交一个 PR。看到这一切发生其实有点诡异:你发出一个诸如“重构支付模块以支持 X”的命令,过一会儿就会收到一个包含代码变更且测试通过的拉取请求。我们确实活在未来。你可以在《从指挥到编排:未来的软件工程》中读到更多相关内容。

不过,这些工具并非万无一失,你必须理解它们的边界。它们极大地加速了编码中偏机械性的部分——生成样板代码、应用重复性修改、自动运行测试——但它们仍然非常依赖你的引导。例如,当我使用 Claude 或 Copilot 这类代理来实现功能时,通常会把前面步骤中的计划或待办清单一并提供给它,让它清楚每一步的执行顺序。如果代理支持,我会在下达执行指令前,把 spec.md 或 plan.md 加载进上下文,以确保它不跑偏。

我们还远未到可以完全放手让 AI 代理无人监督地完成整个功能,并指望它给出完美结果的阶段。 相反,我是以受监督的方式来使用这些工具:我会让它们生成并运行代码,但始终关注每一个步骤,一旦发现异常就及时介入。还有一些编排工具,比如 Conductor,允许你并行运行多个代理处理不同任务(本质上是扩展 AI 助手的规模)。一些工程师已经在尝试同时跑 3–4 个代理,分别负责不同功能。我也试过这种“高度并行”的方式——在短时间内完成大量工作时效果惊人,但同时监控多个 AI 线程在心理上也相当消耗精力!在大多数情况下,我仍然坚持一次只用一个主代理,必要时再加一个用于评审的辅助代理(下面会讲)。

记住,这些都是强力工具——扣动扳机和引导结果的,始终是你。


保持人工介入——对所有内容进行验证、测试和审查

**AI 会非常乐意生成“看起来合理”的代码,但你要为质量负责——始终审查并充分测试。**我最重要的一条原则之一是:绝不盲目信任 LLM 的输出。正如 Simon Willison 在这里所说,把 LLM 结对程序员看作是 **“过度自信、而且容易犯错”**的存在。它会用百分之百的笃定语气写代码——即使其中包含 bug 或胡言乱语——并且除非你发现问题,否则它不会主动告诉你哪里错了。因此,我会把每一段 AI 生成的代码,都当成来自一位初级工程师:逐行阅读、运行、并在需要时测试。你必须测试它写的东西——跑单元测试,或手动验证功能是否真的如它所说那样工作。更多内容可参考《“氛围式编码”并不是低质量工作的借口》。

事实上,我把测试直接织入了整个工作流。前期规划阶段通常就会包含每一步对应的测试列表或测试计划。如果我使用像 Claude Code 这样的工具,我会指示它在完成某个任务后运行测试套件,并在出现失败时自行调试。这种紧密的反馈循环(写代码 → 跑测试 → 修复)正是 AI 擅长的事情——前提是测试存在。因此,那些能最大化利用编码代理的人,往往也是测试实践非常扎实的人。对于像 Claude 这样的代理来说,一个完善的测试套件就像安全网;没有测试时,代理可能会轻率地认为“一切正常”,而实际上已经破坏了好几处。所以,投资测试——它会放大 AI 的价值,并增强你对结果的信心。

即便超越自动化测试,也要做代码评审——包括人工评审和 AI 辅助评审。我经常停下来,逐行审查目前生成的代码。有时我会开启第二个 AI 会话(或使用不同模型),让它去评审第一个模型生成的代码。例如,让 Claude 写代码,然后问 Gemini:“你能帮我检查这个函数是否有错误或改进空间吗?”这常常能发现细微问题。关键在于:不要因为代码是 AI 写的,就跳过评审。恰恰相反,AI 写的代码往往需要更多审查,因为它有时在表面上极具说服力,却隐藏着人类不容易第一时间察觉的缺陷。

我还使用了由我上一支团队构建的 Chrome DevTools MCP,作为调试与质量闭环的一部分,用来弥合静态代码分析与真实浏览器执行之间的鸿沟。它相当于“给 AI 装上眼睛”:允许我授权 AI 工具直接查看浏览器所看到的内容,检查 DOM,获取性能追踪、控制台日志或网络请求记录。这种集成消除了手动切换上下文的摩擦,使得通过 LLM 直接进行自动化 UI 测试成为可能,也让基于真实运行数据的高精度 bug 定位和修复成为现实。

忽视人工监督的严重后果已有记录。一位在赶项目时大量依赖 AI 生成代码的开发者描述最终产物是一个混乱不堪的系统——逻辑重复、方法命名不一致、架构支离破碎。他意识到自己只是不断“构建、构建、再构建”,却从未真正退后一步去理解 AI 编织出来的整体。修复它需要一次痛苦的重构,并发誓再也不让事情失控到这种程度。我对此深有感触。无论我使用多少 AI,我始终是那个负最终责任的工程师。

在实践中,这意味着:只有在我真正理解代码之后,才会合并或发布。如果 AI 生成了过于复杂的实现,我会让它加注释解释,或者干脆自己重写成更简单的形式。如果哪里感觉不对劲,我就会深入调查——就像对待一位人类同事提交的可疑代码一样。

一切归根结底是心态问题:LLM 是助手,而不是可以自主信赖的编码者。我是高级工程师;LLM 的职责是加速我,而不是替代我的判断。坚持这种立场不仅能产出更好的代码,也能保护你自身的成长。(有些人担心过度依赖 AI 会让技能退化——我认为只要你始终在回路中,积极审查并理解每一行代码,你实际上是在以更高速度打磨直觉。)总之:保持警惕,频繁测试,始终评审。 到最后,这仍然是你的代码库。

经常提交代码,并将版本控制作为安全保障。切勿提交自己无法解释的代码。

频繁提交就是你的存档点——它们让你能够撤销 AI 的失误,并理解发生了哪些变化。

当你与一个能够快速生成大量代码的 AI 一起工作时,事情很容易偏离正轨。我通过采用极其细粒度的版本控制习惯来缓解这一问题。我会尽早、并且频繁地提交代码,甚至比正常手写代码时还要频繁。每完成一个小任务,或每一次成功的自动化修改之后,我都会创建一次带有清晰提交信息的 git commit。这样一来,如果 AI 的下一条建议引入了 bug 或者造成了混乱的改动,我就能回退到最近的检查点(或者从中 cherry-pick),而不会丢掉数小时的工作。一位实践者把这种做法比作把提交当成**“游戏里的存档点”**——如果一次 LLM 会话走偏了,你总是可以回滚到上一个稳定的提交。我发现这个建议极其有用。当你知道必要时可以用 git reset 撤销改动时,去尝试一次大胆的 AI 重构就不那么有压力了。

恰当的版本控制在与 AI 协作时同样非常有帮助。由于我不能指望 AI 记住它做过的所有事情(上下文窗口的限制等等),git 历史就成了一份宝贵的日志。我经常浏览最近的提交,向 AI(或向我自己)说明发生了哪些变化。事实上,只要你把提交历史提供给 LLM,它们本身也能利用这些信息——我曾把 git diff 或提交日志直接粘贴到提示词里,让 AI 知道哪些代码是新的,或者之前的状态是什么。有趣的是,LLM 在解析 diff 以及使用诸如 git bisect 之类的工具来定位 bug 引入位置方面真的非常擅长。它们有着无限的耐心去遍历提交历史,这可以极大增强你的调试能力。但前提是:你一开始就要有一份整洁的提交历史。

还有一个好处:带有良好提交信息的小提交,本质上记录了开发过程,这在做代码审查(无论是 AI 还是人类)时非常有帮助。如果一个 AI 一次性做了五个改动,然后某处坏了,把这些改动分散在不同提交中,就更容易定位到底是哪个提交导致了问题。反之,如果所有内容都塞进一个名为“AI changes”的巨大提交里,那就自求多福吧。我因此严格要求自己:完成任务,运行测试,提交。 这也与前面关于把工作拆分成小块的建议非常契合——每一个小块最终都会成为一个独立的提交或 PR。

最后,不要害怕使用分支或 worktree来隔离 AI 实验。我采用的一种进阶工作流(灵感来自 Jesse Vincent 等人)是:为一个新特性或子项目创建一个全新的 git worktree。这样我就可以在同一个仓库上并行运行多个 AI 编码会话而互不干扰,之后再把改动合并回来。这有点像让每个 AI 任务都待在自己的沙箱分支里。如果某个实验失败了,我就直接丢弃那个 worktree,主分支不会受到任何影响;如果成功了,再把它合并进来。当我一边让 AI 实现特性 A,一边由我自己(或另一个 AI)实现特性 B 时,这种方式尤为关键。正是版本控制让这种协同成为可能。简而言之:频繁提交,用分支组织工作,并拥抱 git,把它作为控制机制,来让 AI 生成的改动保持可控且可逆。

通过规则和示例来定制 AI 的行为

通过提供风格指南、示例,甚至“规则文件”来引导你的 AI 助手——前期做一点调校,就能显著提升输出质量。

我学到的一点是:你不必接受 AI 的默认风格或做事方式——只要给它一些明确的指引,就可以对其行为产生很强的影响。举例来说,我维护了一个会定期更新的 CLAUDE.md 文件,其中包含希望 Claude(Anthropic 的模型)遵循的流程规则和偏好(使用 Gemini CLI 时也有类似的 GEMINI.md)。这些内容包括诸如“按照我们项目的代码风格编写代码、遵循我们的 lint 规则、不使用某些函数、偏好函数式而非 OOP”等。当我开始一个会话时,会把这个文件提供给 Claude,使其与我们的约定保持一致。正如 Jesse Vincent 在其文章中提到的,这种方式在让模型“保持正轨”方面效果出奇地好——它能显著降低 AI 偏离脚本或引入我们不希望出现的模式的概率。

即便没有花哨的规则文件,你也可以通过自定义指令或 system prompt 来定调。GitHub Copilot 和 Cursor 都引入了相关功能,允许你在项目层面全局配置 AI 的行为。我就充分利用了这一点,写了一小段关于我们编码风格的说明,例如:“使用 4 空格缩进,在 React 中避免使用箭头函数,偏好描述性变量名,代码需通过 ESLint。”在这些指令就位之后,AI 的建议就会更加贴近人类队友的写法。Ben Congdon 在文章中提到,他很惊讶竟然很少有人使用 Copilot 的自定义指令,因为它们的效果非常显著——只要提前提供一些示例和偏好,他就能引导 AI 输出完全符合团队习惯的代码。我对此深有同感:花点时间教会 AI 你的期望。

另一个非常强大的技巧是提供行内示例,明确你想要的输出格式或实现方式。如果我希望 AI 以一种非常特定的方式来编写函数,我可能会先给它看代码库中已有的类似函数:“这是我们实现 X 的方式,请用类似的方法实现 Y。”如果我想要某种特定的注释风格,我甚至会先自己写一条注释,然后让 AI 按这种风格继续。本质上,这是在对模型进行 预热(prime),让它知道要遵循的模式。LLM 非常擅长模仿——给它一两个例子,它就会沿着同样的路子往下写。

社区中也出现了不少富有创意的“规则集”,用来驯服 LLM 的行为。你可能听说过 “Big Daddy” 规则,或者在提示词中加入“禁止幻觉 / 禁止欺骗”的条款。这些本质上都是在提醒 AI 要保持真实,不要过度编造并不存在的代码。例如,我有时会在提示词前加上一句:“如果你对某些事情不确定,或者缺少代码库上下文,请先请求澄清,而不是编造答案。”这能有效减少幻觉。另一条我常用的规则是:“在修复 bug 时,始终在注释中简要说明你的推理过程。”这样一来,当 AI 生成修复方案时,也会留下类似这样的注释:“// Fixed: Changed X to Y to prevent Z (as per spec).”这对后续审查非常有价值。

总而言之,不要把 AI 当成一个黑箱——要对它进行调校。通过配置 system 指令、共享项目文档,或明确写下规则,你可以把 AI 打造成团队中一个更加专业化的开发者。这就像新员工入职一样:你一定会给他风格指南和一些入门建议,对吧?同样地对待你的 AI 结对编程伙伴即可。投入产出比非常高——你会得到需要更少修改、并且能更顺畅地融入现有代码库的输出。

将测试和自动化视为放大效率的关键杠杆

善用 CI/CD、代码规范检查器和代码审查机器人——AI 在能够自动捕获错误的环境中表现最好。

这是“保持人在回路中并持续提供上下文”的一个自然延伸:一条运转良好的开发流水线会显著提升 AI 的生产力。我会确保所有大量使用 AI 编码的代码仓库,都具备一套健全的持续集成(CI)体系。这意味着:每次提交或 PR 都会自动运行测试,强制执行代码风格检查(如 ESLint、Prettier 等),并且理想情况下,每个新分支都能部署到一个可用的 staging 环境。为什么要这样做?因为我可以让 AI 主动触发这些流程,并据此评估结果。

例如,如果 AI 通过 Jules 或 GitHub Copilot Agent 之类的工具发起了一个 pull request,我们的 CI 就会自动运行测试并报告失败信息。我可以把这些失败日志再喂回给 AI:“集成测试在 XYZ 处失败了,我们来一起调试。”这样一来,修 bug 就变成了一个快速反馈的协作循环,而 AI 非常擅长处理这种模式(它提出修复方案,我们再次运行 CI,然后继续迭代)。

自动化的代码质量检查(如 linter、类型检查器)同样可以对 AI 起到引导作用。我有时甚至会把 linter 的输出直接放进提示词里。如果 AI 写的代码没有通过我们的规范检查,我就把错误信息复制到对话中,说一句:“请解决这些问题。”模型立刻就知道该做什么了。这就像有一位严格的老师在盯着 AI 写代码。根据我的经验,一旦 AI 看到了某个工具的输出(比如测试失败或 lint 警告),它就会非常努力地去修正——毕竟它“想要”给出正确的答案。这再次呼应了“提供上下文”的原则:把环境对其行为的反馈(测试失败等)提供给 AI,它就能从中学习和调整。

AI 编码代理本身也在越来越多地集成自动化钩子。有些代理在所有测试通过之前,甚至不会宣称某个代码任务“完成”——这正是你希望看到的那种严谨态度。代码审查机器人(无论是 AI 还是非 AI)则充当了另一道过滤器——我会把它们的反馈当作额外的改进提示。例如,如果 CodeRabbit 或其他审查者评论说:“这个函数在做 X,这并不理想”,我就会直接问 AI:“你能根据这个反馈进行重构吗?”

当你把 AI 与自动化工具结合起来时,就会形成一个良性循环:AI 写代码,自动化工具发现问题,AI 修复问题,如此反复,而你则把控整体方向。这种感觉就像是拥有一位速度极快的初级开发者,而他的每一次提交都会立刻被一位不知疲倦的 QA 工程师检查。但要记住,是你 搭建了这个环境。如果你的项目缺乏测试或任何自动化检查,AI 的工作就可能夹带着细微的 bug 或质量问题,一直潜伏到很晚才被发现。

因此,展望 2026,我的一个目标就是进一步强化 AI 代码贡献周围的质量门禁:更多测试、更多监控,甚至可能引入“AI 审 AI”的代码评审。听起来或许有些悖论(让 AI 去审查 AI),但我已经见过这种方式抓住了某个模型遗漏的问题。归根结底:一个对 AI 友好的工作流,必然具备强大的自动化——用这些工具来约束并校验 AI 的行为。

持续学习并不断适应(AI 会放大你的技能)

把每一次 AI 编码会话都当作一次学习机会——你知道得越多,AI 就越能帮到你,从而形成一个良性循环。

使用 LLM 进行开发过程中,最令我兴奋的一点在于:在这个过程中学到的东西实在太多了。AI 并没有取代我“需要懂”的那些知识,反而把我带入了一些我原本可能不会主动尝试的新语言、框架和技术领域。

这种模式具有普遍性:如果你具备扎实的软件工程基础,AI 会以成倍的效果放大你的生产力;如果缺乏这种基础,AI 可能只会放大混乱。许多经验丰富的开发者都观察到,LLM 会“奖励既有的最佳实践”——清晰的需求说明、完善的测试、规范的代码评审等等,在引入 AI 之后都会变得更加有威力。以我的经验来看,AI 让我能够在更高的抽象层级上工作(专注于设计、接口和架构),而把样板代码的生成交给它;但前提是,我必须先具备这些高层次能力。正如 Simon Willison 所指出的,几乎所有定义一名资深工程师的能力(系统设计、复杂度管理、判断哪些该自动化、哪些该手写)正是如今使用 AI 获得最佳效果的关键。因此,使用 AI 反而促使我提升自己的工程水准——我在规划上更加严谨,在架构上更加自觉,因为我实际上是在“管理”一位速度极快但略显天真的程序员(也就是 AI)。

对于那些担心使用 AI 会削弱自身能力的人,我的看法恰恰相反——前提是用对方式。通过审阅 AI 写的代码,我接触到了新的惯用写法和解决思路;通过调试 AI 的错误,我加深了对语言本身以及问题领域的理解。我经常要求 AI 解释它的代码或修复背后的理由——有点像不断让候选人讲解自己的代码——而我也能从它的回答中获得启发。我还把 AI 当作研究助理:当我对某个库或某种方案不确定时,就让它列举选项、比较取舍。这就像随时有一位百科全书式的导师待命。所有这些,都让我成为了一个更有知识深度的程序员。

从宏观来看,AI 工具是在放大你的专业能力。展望 2026 年,我并不担心它们“抢走我的工作”——相反,我很期待它们把我从繁琐重复的劳动中解放出来,让我能把更多时间投入到软件工程中更具创造性、更复杂的部分。但我也清醒地认识到,对于没有扎实基础的人来说,AI 可能会把“邓宁–克鲁格效应”放大到极致(你可能 感觉 自己做出了很棒的东西,直到它彻底崩塌)。因此,我的建议是:持续打磨你的基本功,并用 AI 来加速这一过程;同时,也要有意识地定期在不使用 AI的情况下编码,以保持原始技能的敏锐度。最终,“开发者 + AI”的组合远比任何一方单独行动更强大,而这个组合中的开发者那一半,必须足够可靠。

结论

随着我们迈入 2026 年,我已经在开发工作流中全面拥抱了 AI——但这是以一种深思熟虑、由专家驱动的方式进行的。我的方法本质上是 “AI 增强的软件工程”,而非 AI 自动化的软件工程。

我学到的一点是:当你在 AI 协作中运用经典的软件工程纪律时,效果最佳。事实证明,我们辛苦积累的所有实践——先设计再编码、编写测试、使用版本控制、维持标准——不仅仍然适用,而且在 AI 编写一半代码时显得更加重要。

我对未来充满期待。工具在不断改进,而我的工作流也必将随之演进。也许完全自主的“AI 开发实习生”将承担更多重复性工作,而我们专注于更高层次的任务;也许会出现新的调试和代码探索范式。不管怎样,我计划始终保持 在回路中——引导 AI、向它们学习,并负责任地放大我的生产力。

对我而言的核心结论是:AI 编码助手是令人难以置信的倍增器,但人类工程师仍是整个流程的导演。

在此,祝大家在 2026 年构建顺利!🚀

我很高兴地分享,我已经与 O’Reilly 一起发布了一本新的 AI 辅助工程书籍。书籍网站上也有一些免费的实用技巧,感兴趣的可以查看。

最近读到一篇介绍 Pydantic 生态的文章,提到 pydantic-settings 库除了可以简化应用配置外,还可以用来创建命令行应用。在参阅了相关文档后,我完成了一个简单的示例,体验相当不错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# /// script
# requires-python = ">=3.13"
# dependencies = ["pydantic-settings"]
# ///
import logging
from typing import Annotated, Literal

from pydantic import AliasChoices, Field, BeforeValidator
from pydantic_settings import BaseSettings, CliApp


class Settings(
BaseSettings, cli_parse_args=True, cli_prog_name="sum", cli_enforce_required=True
):
"""A simple CLI app to sum numbers."""

num: Annotated[list[int], Field(description="Numbers to sum")]
verbose: Annotated[
Literal[0, 1],
Field(
default=0,
validation_alias=AliasChoices("v", "verbose"),
description="Enable verbose output",
),
BeforeValidator(lambda v: int(v)),
]

def cli_cmd(self):
if self.verbose:
logging.basicConfig(level=logging.DEBUG, format="%(message)s")
logging.debug("Calculating sum of numbers %s", self.num)
print(sum(self.num))


if __name__ == "__main__":
CliApp.run(Settings)

可以直接使用 uv 运行该脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 自动生成帮助信息

➜ uv run --script cli.py --help
usage: sum [-h] --num list[int] [-v {0,1}]

A simple CLI app to sum numbers.

options:
-h, --help show this help message and exit
--num list[int] Numbers to sum (required)
-v, --verbose {0,1} Enable verbose output (default: 0)

# 必填参数检查(开启 cli_enforce_required)

➜ uv run --script cli.py
usage: sum [-h] --num list[int] [-v {0,1}]
sum: error: the following arguments are required: --num

# 传入参数

➜ uv run --script cli.py --num 1 --num 2 --num 3
6

# 修改默认参数

➜ uv run --script cli.py --num 1 --num 2 --num 3 -v 1
Calculating sum of numbers [1, 2, 3]
6

# 传入 JSON 格式的参数

➜ uv run --script cli.py --num="[1,2,3]"
6

为什么我不看好豆包手机

想象一下你拥有一台自带 AI 助手的手机,想让它帮你用微信发送最近拍摄的合同照片给张总。

若是像以豆包手机为典型的基于屏幕内容读取和模拟点击操作的 AI 手机,大概会按照以下步骤来操作:

  1. 打开相册应用,使用 OCR 技术或多模态大语言模型分析每一张最近拍摄的照片,找到所需的合同照片。
  2. 调用相册应用的分享功能,使用微信分享。
  3. 在微信分享页面通过搜索好友昵称或翻看好友列表的方式,找到张总的账号,输入备注(“张总,这是上次的合同照片”之类)完成分享。

过程中可能会弹出多次授权请求,让用户同意 AI 打开并操作相册、微信等应用。当然不讲究的用户可能在首次配置 AI 手机的时候就永久授予了大部分常见应用的操作权限。

期间 AI 助手会分析识别手机相册中的近期照片(其中可能有家人近照,证件照等敏感照片),获取你的微信好友列表(以及经常互相分享的亲密联系人),给微信好友发消息。并且由于分析照片内容会消耗不少时间,总耗时可能也会长达一分钟以上。

简单来说,这些行为是对隐私和信息安全的极大侵犯,而且并未明显为用户节省时间。

侵犯隐私,安全隐患,效率低下,这就是我对目前讨论火热的豆包手机的看法。

问题的根源在于,若 AI 助手依赖通过读取屏幕内容的方式获取上下文信息,不可避免地需要频繁通过 AI 模型分析手机屏幕上的所有元素。

手机屏幕上往往不只是 AI 助手当前任务需要的信息。比如在上文提的示例中,AI 助手会读取多张图片的内容,直到它找到了合同的照片。并且 AI 助手在微信分享的联系人列表中找到张总之前,可能已经读取了用户大部分的联系人微信昵称和头像,毕竟按拼音排序张总大概率在列表的很后面的位置。同理,在让 AI 帮你在淘宝购买商品的场景下,AI 会获取你的首页推荐商品列表,最近订单,收货地址等隐私信息。即使用的是不联网的端侧模型,我也对 AI 手机们能否妥善处理这些隐私信息持怀疑态度。

当前 AI 模型识别图片需要的时间明显要长于人类,对于普通人来说从相册内的一堆图片中中找到合同照片轻而易举,而 AI 模型不可避免地要一张一张照片的读取并识别(大概率不会同时分析多张照片,端侧模型来不具有满足此类功能需求的性能,对于远程 AI 接口来说这样做成本会相当高)。对人类来说不到十秒的操作,AI 可能需要花费十分钟才能完成,期间用户还不能正常使用手机,实在不是多么优秀的体验。

此外 AI 手机可能还会出现误删除重要文件,发送错误信息给联系人等危险操作。毕竟作为相对很成熟 AI 编程领域,行业领先的 Google Gemini 3.0 Pro 都犯过删除用户整个磁盘文件的错误。尤其是当 AI 手机完成简单的日常操作十分优秀,用户为了省事不再逐一仔细检查 AI 手机的行为默认授权后,往往会有潜在的巨大安全隐患。

综上,不论豆包手机在二手平台炒到到了几万元的高级,它终究不是我理想中的 AI 手机的最佳形态。

我最近使用 Github Copilot Agent 模式的频率大幅增加,在接近月底的时候已经达到了 80%的高级请求使用额度,有必要准备一个备用的 AI 开发工具。
目前比较流行的终端 AI 开发工具非 Claude Code 莫属了(OpenAI 的 Codex 我有使用过,有点倾向于埋头几分钟进行一堆更改,可控性没有 Claude Code 高),但国内环境使用 Claude 模型比较困难,此时可以选择在 Claude Code 中使用国产模型,比如GLM 4.6MinMax M2,只需要修改 claude code 的默认配置就好了。。

.claude/settings.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic",
"ANTHROPIC_AUTH_TOKEN": "Your API Key",
"API_TIMEOUT_MS": "3000000",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": 1,
"ANTHROPIC_MODEL": "MiniMax-M2",
"ANTHROPIC_SMALL_FAST_MODEL": "MiniMax-M2",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "MiniMax-M2",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "MiniMax-M2",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "MiniMax-M2"
}
}

引言

Python 3.13 版本引入了 (No-GIL 模式),彻底解决了长期存在的并发性能瓶颈问题。随着Python 3.14的发布,Non-GIL 模式更加稳定。本文通过一个计算密集型任务的实际测试,对比 GIL 模式和 No-GIL 模式的性能差异,展示 Python 3.14 在多线程场景下的显著提升。

测试环境

  • 操作系统: Ubuntu 24.04 (WSL 环境)
  • Python 版本:
    • GIL 模式: Python 3.14
    • No-GIL 模式: Python 3.14t (Thread-Free)
  • 执行工具: uv (高性能 Python 包安装器和解析器)
  • 硬件配置: ThinkBook 14 , i5-13500H (2.60 GHz), 32GB RAM

测试方案设计

我们设计了一个计算密集型任务:计算 1 到 1,000,000 的平方和。通过以下方式验证并行性能:

  1. 任务分解:

    • 将数据集划分为与 CPU 核心数相等的块
    • 每个线程处理一个数据块
  2. 计算函数:

1
2
def sum_of_squares(numbers: list[int]):
return reduce(lambda x, y: x + y**2, numbers)
  1. 并发框架:
    • 使用 ThreadPoolExecutor 实现线程池
    • 每次测试运行 10 次取平均值

测试代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from concurrent.futures import ThreadPoolExecutor
from functools import reduce
from time import perf_counter
import os

def sum_of_squares(numbers: list[int]):
"""计算数字列表的平方和"""
return reduce(lambda x, y: x + y**2, numbers)

if __name__ == "__main__":
MAX_WORKERS = os.cpu_count()
print(f"Using {MAX_WORKERS} threads")

# 创建测试数据集 (1-1,000,000)
numbers = list(range(1, 1000001))

# 数据分块
chunk_size = len(numbers) // MAX_WORKERS
chunks = [numbers[i : i + chunk_size] for i in range(0, len(numbers), chunk_size)]

total_time = 0
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
for _ in range(10): # 运行10次取平均
start = perf_counter()
results = list(executor.map(sum_of_squares, chunks))
end = perf_counter()
total_time += end - start

average_time = total_time / 10
print(f"Average time over 10 runs: {average_time:.4f} seconds")
Read more »