🎩 百行代码的魔法:当复杂遇见简单
> *"如果你不能向一个六岁的孩子解释清楚,那你自己也没有真正理解。"* > > *——理查德·费曼*
---
你有没有想过,为什么现在的 AI 框架动辄几十万行代码?它们像一座座宏伟的摩天大楼,电梯、空调、消防系统一应俱全——但你只是想煮一杯咖啡而已。
今天,我要给你讲一个关于"减法"的故事。一个哥伦比亚大学的博士生,在用腻了那些臃肿的框架后,决定回到原点。他问了一个看似愚蠢的问题:"如果我把一切都去掉,最少需要多少行代码才能构建一个可用的 LLM 框架?"
答案是:100 行。
这就是 PocketFlow——一个用 Python 写的、零依赖、零供应商锁定的极简框架。它的创造者 Zachary Huang 即将加入微软研究院,他用这 100 行代码告诉我们:真正的优雅不是添加,而是删减到不能再删减。
---
🧩 第一部分:厨房里的计算机科学
想象你走进一家餐厅的后厨。
你会看到什么?切菜台、炉灶、装盘区——每个区域各司其职。厨师们不是挤在一起乱作一团,而是有秩序地传递食材:切好的菜送到炉灶,炒好的菜送到装盘区。
PocketFlow 的核心洞察就是这个:所有的 AI 系统,本质上就是一个井然有序的厨房。
> 小贴士:这里的"AI 系统"可以是聊天机器人、搜索引擎、数据分析工具——任何让大语言模型(LLM)帮你完成任务的程序。
三个简单的构建块
PocketFlow 把整个系统拆成了三个部分,就像厨房里的三个基本元素:
节点(Node) 是干活的地方。每个节点只做三件事:
1. Prep(准备):从中央操作台拿取需要的食材 2. Exec(执行):专心完成自己的任务 3. Post(收尾):把成果放回操作台,并告诉下一个节点该做什么
用代码表示,就是这么简单:
class BaseNode:
def prep(self, shared): pass # 读取数据
def exec(self, prep_res): pass # 执行任务
def post(self, shared, prep_res, exec_res): pass # 写回结果
你可能会问:就这?
对,就这。但简单不等于弱小。
> 小贴士:分离关注点(Separation of Concerns)是软件工程的核心原则。Prep 管数据读取,Exec 管计算逻辑,Post 管数据写入——三者互不干扰。
流程(Flow):菜谱的艺术
如果说节点是厨房里的工位,那 Flow(流程) 就是菜谱——它告诉你做完这一步该去哪一步。
class Flow(BaseNode):
def orch(self, shared):
curr = self.start
while curr:
action = curr.run(shared)
curr = self.get_next_node(curr, action)
就是一个简单的循环,根据每个节点的返回值决定下一步去哪。
---
🔄 第二部分:有向图的魔力
PocketFlow 的核心洞察是:所有的 LLM 应用,本质上都是对有向图的遍历。
如果让节点可以回到自己呢?
这就变成了一个循环。节点执行完后,根据返回值,流程又把它自己设为下一个节点。于是对话可以一直进行下去。
如果让两个节点互相跳转呢?
这就构成了一个搜索智能体:决策节点判断是否需要搜索,搜索节点获取信息,然后回到决策节点,直到信息足够再生成答案。
传统框架(如 LangChain)把常见模式封装成特定类,但代价是臃肿和难以定制。PocketFlow 给你最基础的积木,你想搭什么,自己搭。
---
🤖 第三部分:实战——搜索智能体
用 PocketFlow 搭建一个类似 Perplexity AI 的搜索智能体:
class DecideAction(Node):
def prep(self, shared):
return shared["question"], shared.get("results", [])
def exec(self, inputs):
return call_llm(f"需要搜索吗?问题:{inputs[0]}")
def post(self, shared, prep_res, exec_res):
return "search" if "yes" in exec_res else "answer"
class SearchWeb(Node):
def exec(self, question):
return web_search(question)
def post(self, shared, prep_res, exec_res):
shared["results"] = exec_res
return "decide"
class AnswerQuestion(Node):
def exec(self, inputs):
return call_llm(f"基于{inputs[1]}回答问题:{inputs[0]}")
def post(self, shared, prep_res, exec_res):
shared["answer"] = exec_res
# 连接节点
decide - "search" >> search
decide - "answer" >> answer
search - "decide" >> decide
flow = Flow(start=decide)
flow.run({"question": "谁赢得了2023年超级碗?"})
就这么简单。清晰的逻辑,完全的掌控。
---
🚀 第四部分:智能体编码——人机协作的未来
PocketFlow 开启了智能体编码(Agentic Coding):让 AI 帮你写 AI 应用。
想象盖房子:
- 你是建筑师:提供愿景和关键决策
- AI 是建筑队:处理具体实现
- 你负责验收:审查和完善成果
为什么 PocketFlow 适合智能体编码?
传统框架把功能固化在代码中,导致代码库膨胀到几十万行,文档滞后。
PocketFlow 的解决方案:极简核心代码(100 行)+ 丰富文档生态。文档不仅仅是给人看的,更是 AI 助手的"指导手册"。通过 .cursorrules 文件,Cursor 等 AI 工具能快速掌握 PocketFlow 的设计理念,为特定需求生成完美契合的解决方案。
更令人振奋的是:随着 PocketFlow 代码进入未来大模型的训练数据,AI 助手将自然而然地掌握这些原则,让 LLM 应用开发真正畅通无阻!
---
🌟 第五部分:返璞归真
PocketFlow 颠覆了"更复杂才更强大"的传统思维。它用 100 行代码证明:真正的技术突破源于本质洞察,而非堆砌抽象。
核心启示
| 传统框架 | PocketFlow |
|---|---|
| 几十万行代码 | 100 行代码 |
| 复杂抽象层 | 零臃肿 |
| 供应商锁定 | 零依赖 |
| 功能固化在代码中 | 功能存在于文档中 |
| 难以定制 | 完全掌控 |
适用场景
- 多智能体系统(Multi-Agents)
- 工作流自动化(Workflow)
- 检索增强生成(RAG)
- 映射归约处理(Map-Reduce)
- 流式数据处理(Streaming)
📝 结语
Zachary Huang 用 100 行代码告诉我们:简洁并不意味着能力有限,恰恰相反,它赋予了开发者最大的自由和掌控力。
正如伟大设计遵循的原则:"不是无法再添加,而是无法再简化时,才达到完美。"
下次当你面对一个复杂的 AI 框架时,不妨问问自己:"这真的是必需的吗?如果去掉一切,最少需要什么?"
也许,答案比你想象的简单得多。
---
📚 参考资料
1. PocketFlow GitHub: https://github.com/The-Pocket/PocketFlow 2. 官方文档: https://the-pocket.github.io/PocketFlow/ 3. 作者博客: https://pocketflow.substack.com/p/i-built-an-llm-framework-in-just 4. Agentic Coding: https://zacharyhuang.substack.com/p/agentic-coding-the-most-fun-way-to 5. Datawhale 中文教程: https://github.com/datawhalechina/easy-pocket
---
*"完美不是无以复加,而是无可删减。"*
*——安托万·德·圣埃克苏佩里*
#科普 #AI #PocketFlow #LLM框架 #费曼风格 #小凯