响应快2-3倍的秘密:claude-code-from-scratch流式输出与并行工具执行原理详解
【免费下载链接】claude-code-from-scratchBuild your own Claude Code from scratch. 🔍 Claude Code 开源了 50 万行代码,读不动?用 ~5000 行 TypeScript / Python 从零复现核心架构,11 章分步教程带你理解 coding agent 精髓项目地址: https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch
如果你用过 Claude Code,一定注意到它打字飞快、工具响应迅速。claude-code-from-scratch 用约 5000 行 TypeScript / Python 代码从零复现了这套 Coding Agent 的核心架构,其中「流式输出 + 并行工具执行」正是它响应快 2-3 倍的关键原理。本文带你用 5 分钟看懂这两大机制是如何实现的。
为什么流式输出如此重要?
先理解一个体验问题:
- 模型生成速度约为每秒 30-80 个 token,一段稍长的回答需要 10-30 秒
- 用户面对空白屏幕的忍耐极限只有 2-3 秒
如果采用「一次性返回」,用户要干等几十秒;而流式输出让第一个字在几百毫秒内出现,把「等待 30 秒」变成「看着内容逐渐写出来」,主观等待感接近归零。
📖 完整原理讲解见第 5 章教程:docs/05-streaming.md
底层基于 SSE(Server-Sent Events):服务端用一条持久 HTTP 连接持续推送数据,每生成几个 token 就推一个content_block_delta事件。
原理一:流式输出,边生成边显示
传统调用方式是「一次性等完整个回复」,答案会「啪」地一下全部出现。流式调用只需要把这一处请求换成 stream 模式:
// 非流式:等完整响应 const reply = await client.messages.create(request); // 流式:边生成边打印,最后再收集完整消息 const stream = client.messages.stream(request); stream.on("text", (t) => process.stdout.write(t)); // 逐字显示 const reply = await stream.finalMessage();核心就三步:
- 发起流式请求—— 使用
messages.stream替代messages.create - 监听 text 事件—— 每收到一小段文本立即打印到屏幕
- 等待 finalMessage—— 拿到与非流式调用完全相同结构的完整消息,供后续逻辑使用
对应源码在 src/agent.ts(TypeScript 版callAnthropicStream)和 python/mini_claude/agent.py(Python 版_call_anthropic_stream)。
项目同时支持 Anthropic 与 OpenAI 兼容两套后端:Anthropic 后端由 SDK 封装了全部 SSE 解析细节;OpenAI 后端的 tool_calls 参数是分片到达的,需要按index手动累积重组,这部分实现同样在callOpenAIStream中。
原理二:流式工具执行,把等待「藏」起来
这是让响应提速的第一个真正秘密。
模型一次回复中往往会调用多个工具。传统流程是:等整个 API 响应结束 → 再开始执行工具。而流式工具执行的思路是——每个tool_use内容块一接收完整(content_block_stop事件触发),只要它是并发安全且权限允许,就立即开始执行,不必等待整段回复生成完毕。
时间线对比一下(假设流式窗口 10 秒,工具执行 2 秒):
| 方式 | 总耗时 |
|---|---|
| 串行:先生成完 → 再执行工具 | 10s + 2s = 12s |
| 流式执行:生成途中就启动工具 | ≈10s(2s 被「藏」进生成窗口) |
实现上只需一个小 Map 记录提前启动的任务:
// 流式过程中:工具块一完成就提前执行 const earlyExecutions = new Map<string, Promise<string>>(); earlyExecutions.set(block.id, this.executeToolCall(block.name, input)); // 响应结束后:直接 await 早已在跑的任务 const raw = await earlyExecutions.get(toolUse.id);完整实现见 src/agent.ts。注意三个安全细节:
- 🔒只有只读工具才会提前执行(
read_file、list_files、grep_search、web_fetch),写操作和命令执行绝不会抢跑 - ✅权限检查仍然生效,需要用户确认的工具不会被提前触发
- 📦 由于工具执行与模型生成并行,文件读取(通常 <100ms)在流结束时往往已经就绪
原理三:并行工具执行,多任务齐头并进
第二个秘密是并行执行。当模型一次要求读取 3-5 个文件时,逐个串行读取太慢了。
首先标记哪些工具是并发安全的(只读、无副作用,可以同时跑):
// src/tools.ts export const CONCURRENCY_SAFE_TOOLS = new Set([ "read_file", "list_files", "grep_search", "web_fetch" ]);定义在 src/tools.ts。对于不支持流式工具事件的 OpenAI 兼容后端,采用显式批量并行策略:
- 分组:把连续的并发安全工具归入同一批次
- 并行:同一批次用
Promise.all(Python 版用asyncio.gather)一次性执行 - 保序:写操作前后各自独立成批,绝不跨越写操作并行
例如[read, read, write, read]会被分为[read||read]、[write]、[read]三个批次,写操作独占一批,保证安全。
实现细节见 src/agent.ts。
两种后端策略小结:
| 后端 | 并行策略 | 效果 |
|---|---|---|
| Anthropic | 流式执行天然并行:工具块完整即启动 | 执行时间重叠进生成窗口 |
| OpenAI 兼容 | 响应完成后分批Promise.all | 连续只读工具同时执行 |
当模型在一次响应中读取 3-5 个文件时,并行执行通常带来 2-3 倍的速度提升——这就是标题中那个倍数的来源。
动手跑起来:一条命令验证效果
教程的每一章都配有可直接运行的最小实现,无需 API key,用本地 mock 模型驱动。想亲眼看看流式输出 + 工具执行的效果:
git clone https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch cd claude-code-from-scratch npm install node steps/run.mjs 5 # 运行第 5 章:流式输出演示 node steps/run.mjs 5 --diff # 对比查看本章比上一章新增的代码运行脚本见 steps/run.mjs,各章节快照由 steps/canonical/ 下的标准源码生成,保证文档、代码、运行输出三者完全一致。
总结:三大原理一图流
流式输出 ──→ 逐字显示,消除"空白等待" └── 流式工具执行 ──→ 工具块完成即启动,耗时藏进生成窗口 └── 并行工具执行 ──→ 连续只读工具 Promise.all 同时跑 ↓ 整体响应提速 2-3 倍想继续深入?推荐阅读:
- 流式与双后端完整教程:docs/05-streaming.md
- Agent 主循环实现:src/agent.ts
- Python 版实现:python/mini_claude/agent.py
- 下一章权限系统(保护你的系统安全):docs/06-permissions.md
理解流式输出与并行工具执行后,你就掌握了 Coding Agent 性能优化的精髓——这 5000 行代码,正是读懂真实几十万行 Claude Code 的最佳阶梯。
【免费下载链接】claude-code-from-scratchBuild your own Claude Code from scratch. 🔍 Claude Code 开源了 50 万行代码,读不动?用 ~5000 行 TypeScript / Python 从零复现核心架构,11 章分步教程带你理解 coding agent 精髓项目地址: https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考