PocketFlow 循序渐进指南
PocketFlow 是一个 100 行的极简 LLM 框架,用于构建智能体、任务分解、RAG 等应用。本指南将通过循序渐进的方式,带你深度理解其核心设计并学会构建各种 AI 应用。
pip install pocketflow
目录
核心概念
1. 核心抽象:Node
Node 是 PocketFlow 的最小构建块,每个 Node 都有三个步骤:
prep(shared)
- 从共享存储读取和预处理数据exec(prep_res)
- 执行计算逻辑(通常是 LLM 调用)post(shared, prep_res, exec_res)
- 后处理并写回共享存储,返回下一步动作
class SimpleNode(Node):
def prep(self, shared):
return shared["input_text"]
def exec(self, text):
return call_llm(f"处理文本: {text}")
def post(self, shared, prep_res, exec_res):
shared["result"] = exec_res
return "default" # 返回动作名称
2. 核心抽象:Flow
Flow 通过 Action 连接多个 Node,形成有向图:
# 基础连接
node_a >> node_b # 默认连接(action="default")
# 条件分支
node_a - "success" >> node_b
node_a - "error" >> error_handler
# 创建 Flow
flow = Flow(start=node_a)
flow.run(shared)
3. 通信机制
Shared Store 是全局数据字典,所有 Node 都可以读写:
shared = {
"input": "用户输入",
"results": {},
"config": {...}
}
基础应用
应用1:简单文本处理流水线
我们先从最基础的文本处理开始,了解 Node 和 Flow 的基本用法。
架构图
flowchart TD
A[用户输入] --> B[文本清理]
B --> C[情感分析]
C --> D[生成回复]
D --> E[输出结果]
classDef nodeStyle fill:#e1f5fe,stroke:#01579b,stroke-width:2px
class B,C,D nodeStyle
代码实现
from pocketflow import Node, Flow
def call_llm(prompt):
"""简单的LLM调用函数"""
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
class TextCleanNode(Node):
"""文本清理节点"""
def prep(self, shared):
return shared["user_input"]
def exec(self, text):
# 简单的文本清理
cleaned = text.strip().lower()
return cleaned
def post(self, shared, prep_res, exec_res):
shared["cleaned_text"] = exec_res
return "default"
class SentimentAnalysisNode(Node):
"""情感分析节点"""
def prep(self, shared):
return shared["cleaned_text"]
def exec(self, text):
prompt = f"分析这段文本的情感倾向(积极/消极/中性):{text}"
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["sentiment"] = exec_res
return "default"
class ResponseGeneratorNode(Node):
"""回复生成节点"""
def prep(self, shared):
return shared["cleaned_text"], shared["sentiment"]
def exec(self, inputs):
text, sentiment = inputs
prompt = f"基于文本:'{text}' 和情感:'{sentiment}',生成一个合适的回复"
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["response"] = exec_res
# 创建流水线
def create_text_processing_pipeline():
clean_node = TextCleanNode()
sentiment_node = SentimentAnalysisNode()
response_node = ResponseGeneratorNode()
# 连接节点
clean_node >> sentiment_node >> response_node
return Flow(start=clean_node)
# 使用示例
def main():
shared = {
"user_input": "今天天气真好!我很开心。"
}
pipeline = create_text_processing_pipeline()
pipeline.run(shared)
print(f"原始输入:{shared['user_input']}")
print(f"清理后:{shared['cleaned_text']}")
print(f"情感分析:{shared['sentiment']}")
print(f"生成回复:{shared['response']}")
if __name__ == "__main__":
main()
学习要点
- 关注点分离:每个 Node 只负责一个特定任务
- 数据流:通过 shared store 在节点间传递数据
- 简单连接:使用
>>
操作符连接节点
应用2:带条件分支的智能客服
接下来我们学习如何使用条件分支处理不同类型的用户请求。
架构图
flowchart TD
A[用户输入] --> B[意图识别]
B -->|查询| C[信息查询]
B -->|投诉| D[投诉处理]
B -->|其他| E[通用回复]
C --> F[格式化输出]
D --> F
E --> F
classDef nodeStyle fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
classDef branchStyle fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
class B branchStyle
class C,D,E,F nodeStyle
代码实现
class IntentClassificationNode(Node):
"""意图识别节点"""
def prep(self, shared):
return shared["user_input"]
def exec(self, text):
prompt = f"""
分析用户意图,只返回以下之一:query, complaint, other
用户输入:{text}
"""
return call_llm(prompt).strip().lower()
def post(self, shared, prep_res, exec_res):
shared["intent"] = exec_res
return exec_res # 返回意图作为 action
class QueryHandlerNode(Node):
"""查询处理节点"""
def prep(self, shared):
return shared["user_input"]
def exec(self, text):
prompt = f"这是一个查询请求,请提供相关信息:{text}"
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["response"] = f"查询结果:{exec_res}"
return "format"
class ComplaintHandlerNode(Node):
"""投诉处理节点"""
def prep(self, shared):
return shared["user_input"]
def exec(self, text):
prompt = f"这是一个投诉,请给出专业的回应:{text}"
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["response"] = f"投诉处理:{exec_res}"
return "format"
class DefaultHandlerNode(Node):
"""默认处理节点"""
def prep(self, shared):
return shared["user_input"]
def exec(self, text):
prompt = f"给出友好的通用回复:{text}"
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["response"] = f"通用回复:{exec_res}"
return "format"
class FormatOutputNode(Node):
"""输出格式化节点"""
def prep(self, shared):
return shared["response"]
def exec(self, response):
# 简单的格式化
return f"🤖 客服助手:{response}"
def post(self, shared, prep_res, exec_res):
shared["final_response"] = exec_res
# 创建智能客服流程
def create_customer_service_flow():
intent_node = IntentClassificationNode()
query_node = QueryHandlerNode()
complaint_node = ComplaintHandlerNode()
default_node = DefaultHandlerNode()
format_node = FormatOutputNode()
# 设置分支逻辑
intent_node - "query" >> query_node
intent_node - "complaint" >> complaint_node
intent_node - "other" >> default_node
# 所有处理节点都连接到格式化节点
query_node - "format" >> format_node
complaint_node - "format" >> format_node
default_node - "format" >> format_node
return Flow(start=intent_node)
# 测试多种输入
def test_customer_service():
test_cases = [
"我想查询我的订单状态",
"你们的服务太差了,我要投诉!",
"今天天气怎么样?"
]
flow = create_customer_service_flow()
for user_input in test_cases:
shared = {"user_input": user_input}
flow.run(shared)
print(f"用户:{user_input}")
print(f"意图:{shared['intent']}")
print(f"回复:{shared['final_response']}")
print("-" * 50)
if __name__ == "__main__":
test_customer_service()
学习要点
- 条件分支:使用
node - "action" >> next_node
设置条件跳转 - 动态路由:根据计算结果决定下一步执行哪个节点
- 收敛节点:多个分支可以汇聚到同一个后续节点
进阶模式
模式1:Batch 批处理 - 批量文档摘要
当需要处理大量数据时,BatchNode 可以将任务分解为小块并行处理。
架构图
flowchart TD
A[多个文档] --> B[BatchNode: 文档处理]
B --> C[文档1摘要]
B --> D[文档2摘要]
B --> E[文档N摘要]
C --> F[合并摘要]
D --> F
E --> F
F --> G[最终报告]
classDef batchStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef processStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
class B batchStyle
class C,D,E,F,G processStyle
代码实现
from pocketflow import BatchNode
class DocumentBatchProcessor(BatchNode):
"""批量文档处理节点"""
def prep(self, shared):
# 返回文档列表,每个元素将被单独处理
documents = shared["documents"]
return list(documents.items()) # [(filename, content), ...]
def exec(self, doc_item):
filename, content = doc_item
# 为每个文档生成摘要
prompt = f"请为以下文档生成100字摘要:\n{content}"
summary = call_llm(prompt)
return (filename, summary)
def post(self, shared, prep_res, exec_res_list):
# exec_res_list 包含所有文档的处理结果
summaries = dict(exec_res_list)
shared["individual_summaries"] = summaries
return "default"
class SummaryCombinerNode(Node):
"""摘要合并节点"""
def prep(self, shared):
return shared["individual_summaries"]
def exec(self, summaries):
# 将所有摘要合并成最终报告
summary_text = "\n\n".join([
f"📄 {filename}:\n{summary}"
for filename, summary in summaries.items()
])
prompt = f"""
基于以下各文档摘要,生成一个综合报告:
{summary_text}
请提供:
1. 总体概述
2. 关键发现
3. 建议行动
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["final_report"] = exec_res
# 创建批处理流程
def create_batch_document_processor():
batch_processor = DocumentBatchProcessor()
combiner = SummaryCombinerNode()
batch_processor >> combiner
return Flow(start=batch_processor)
# 使用示例
def test_batch_processing():
documents = {
"报告1.txt": "这是第一份技术报告,主要讨论AI在医疗领域的应用...",
"报告2.txt": "这是第二份市场分析报告,分析了当前AI市场趋势...",
"报告3.txt": "这是第三份产品规划文档,描述了未来产品发展方向..."
}
shared = {"documents": documents}
flow = create_batch_document_processor()
flow.run(shared)
print("个别摘要:")
for filename, summary in shared["individual_summaries"].items():
print(f"{filename}: {summary[:100]}...")
print("\n综合报告:")
print(shared["final_report"])
if __name__ == "__main__":
test_batch_processing()
模式2:Agent 智能代理 - 研究助手
Agent 模式让 AI 能够根据上下文动态选择行动,实现更复杂的任务处理。
架构图
flowchart TD
A[研究任务] --> B[决策节点]
B -->|搜索| C[网络搜索]
B -->|分析| D[信息分析]
B -->|总结| E[生成报告]
C --> F[更新上下文]
D --> F
F --> B
E --> G[完成]
classDef agentStyle fill:#ffebee,stroke:#c62828,stroke-width:2px
classDef actionStyle fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
classDef contextStyle fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
class B agentStyle
class C,D,E actionStyle
class F contextStyle
代码实现
import yaml
class ResearchAgentNode(Node):
"""研究代理决策节点"""
def prep(self, shared):
task = shared["research_task"]
context = shared.get("research_context", [])
return task, context
def exec(self, inputs):
task, context = inputs
context_text = "\n".join([f"- {item}" for item in context])
prompt = f"""
你是一个研究助手AI。根据当前任务和已有信息,决定下一步行动。
研究任务:{task}
已收集信息:
{context_text}
可选行动:
1. search - 搜索更多相关信息
2. analyze - 分析已有信息并得出洞察
3. report - 生成最终研究报告
请以YAML格式回复:
```yaml
thinking: |
你的思考过程
action: search/analyze/report
parameters:
query: 搜索查询词(如果action是search)
focus: 分析重点(如果action是analyze)
```
"""
response = call_llm(prompt)
yaml_str = response.split("```yaml")[1].split("```")[0].strip()
return yaml.safe_load(yaml_str)
def post(self, shared, prep_res, exec_res):
action = exec_res["action"]
shared["current_action"] = exec_res
return action
class SearchActionNode(Node):
"""搜索行动节点"""
def prep(self, shared):
return shared["current_action"]["parameters"]["query"]
def exec(self, query):
# 模拟搜索(实际应用中可接入真实搜索API)
prompt = f"模拟搜索'{query}'的结果,返回3个关键信息点"
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
context = shared.get("research_context", [])
context.append(f"搜索结果({prep_res}):{exec_res}")
shared["research_context"] = context
return "continue"
class AnalyzeActionNode(Node):
"""分析行动节点"""
def prep(self, shared):
context = shared.get("research_context", [])
focus = shared["current_action"]["parameters"].get("focus", "综合分析")
return context, focus
def exec(self, inputs):
context, focus = inputs
context_text = "\n".join(context)
prompt = f"""
对以下信息进行{focus}:
{context_text}
请提供:
1. 关键洞察
2. 模式识别
3. 进一步研究方向
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
context = shared.get("research_context", [])
context.append(f"分析结果:{exec_res}")
shared["research_context"] = context
return "continue"
class ReportActionNode(Node):
"""报告生成节点"""
def prep(self, shared):
task = shared["research_task"]
context = shared.get("research_context", [])
return task, context
def exec(self, inputs):
task, context = inputs
context_text = "\n".join(context)
prompt = f"""
基于研究任务和收集的信息,生成专业研究报告:
研究任务:{task}
研究过程与发现:
{context_text}
请生成结构化报告,包括:
1. 执行摘要
2. 主要发现
3. 详细分析
4. 结论与建议
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["final_report"] = exec_res
class ContextUpdateNode(Node):
"""上下文更新节点"""
def prep(self, shared):
return len(shared.get("research_context", []))
def exec(self, context_length):
# 简单的继续条件判断
if context_length < 5: # 最多收集5轮信息
return "continue"
else:
return "report"
def post(self, shared, prep_res, exec_res):
return exec_res
# 创建研究代理流程
def create_research_agent():
agent = ResearchAgentNode()
search = SearchActionNode()
analyze = AnalyzeActionNode()
report = ReportActionNode()
update = ContextUpdateNode()
# 设置代理决策分支
agent - "search" >> search
agent - "analyze" >> analyze
agent - "report" >> report
# 行动完成后更新上下文
search - "continue" >> update
analyze - "continue" >> update
# 上下文更新后的决策
update - "continue" >> agent # 循环回到决策
update - "report" >> report # 或生成报告
return Flow(start=agent)
# 使用示例
def test_research_agent():
shared = {
"research_task": "研究量子计算在密码学中的应用前景"
}
flow = create_research_agent()
flow.run(shared)
print("研究过程:")
for i, context in enumerate(shared.get("research_context", []), 1):
print(f"{i}. {context}")
print("\n最终报告:")
print(shared.get("final_report", "未生成报告"))
if __name__ == "__main__":
test_research_agent()
学习要点
- 动态决策:Agent 根据当前状态选择最合适的行动
- 循环控制:通过条件判断控制何时结束循环
- 上下文管理:在多轮交互中积累和利用信息
- 结构化输出:使用 YAML/JSON 格式确保可解析的决策输出
模式3:RAG 检索增强生成 - 智能文档问答
RAG 模式将检索和生成相结合,让 AI 能够基于知识库回答问题。
架构图
flowchart TD
subgraph "离线索引阶段"
A[文档集合] --> B[文档分块]
B --> C[向量化]
C --> D[构建索引]
end
subgraph "在线查询阶段"
E[用户问题] --> F[问题向量化]
F --> G[相似度检索]
G --> H[上下文生成]
H --> I[生成答案]
end
D -.-> G
classDef offlineStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef onlineStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
class A,B,C,D offlineStyle
class E,F,G,H,I onlineStyle
代码实现
# 首先实现一些工具函数
def get_embedding(text):
"""获取文本嵌入向量(示例实现)"""
# 实际应用中应该调用真实的嵌入API
import hashlib
import numpy as np
# 简化的伪嵌入实现
hash_obj = hashlib.md5(text.encode())
seed = int(hash_obj.hexdigest(), 16) % (2**31)
np.random.seed(seed)
return np.random.rand(768).tolist()
def create_simple_index(embeddings):
"""创建简单的向量索引"""
import numpy as np
return np.array(embeddings)
def search_similar(index, query_embedding, top_k=3):
"""搜索最相似的向量"""
import numpy as np
query_emb = np.array(query_embedding)
similarities = np.dot(index, query_emb) / (
np.linalg.norm(index, axis=1) * np.linalg.norm(query_emb)
)
top_indices = np.argsort(similarities)[-top_k:][::-1]
return top_indices, similarities[top_indices]
# 离线索引阶段
class DocumentChunkerNode(BatchNode):
"""文档分块节点"""
def prep(self, shared):
return shared["documents"]
def exec(self, document):
filename, content = document
# 简单按段落分块
chunks = [chunk.strip() for chunk in content.split('\n\n') if chunk.strip()]
return [(filename, i, chunk) for i, chunk in enumerate(chunks)]
def post(self, shared, prep_res, exec_res_list):
all_chunks = []
for chunk_list in exec_res_list:
all_chunks.extend(chunk_list)
shared["chunks"] = all_chunks
class EmbeddingNode(BatchNode):
"""向量化节点"""
def prep(self, shared):
return shared["chunks"]
def exec(self, chunk_info):
filename, chunk_id, text = chunk_info
embedding = get_embedding(text)
return {
"filename": filename,
"chunk_id": chunk_id,
"text": text,
"embedding": embedding
}
def post(self, shared, prep_res, exec_res_list):
shared["embedded_chunks"] = exec_res_list
class IndexBuilderNode(Node):
"""索引构建节点"""
def prep(self, shared):
return shared["embedded_chunks"]
def exec(self, embedded_chunks):
embeddings = [chunk["embedding"] for chunk in embedded_chunks]
index = create_simple_index(embeddings)
return index
def post(self, shared, prep_res, exec_res):
shared["index"] = exec_res
# 在线查询阶段
class QueryEmbeddingNode(Node):
"""查询向量化节点"""
def prep(self, shared):
return shared["question"]
def exec(self, question):
return get_embedding(question)
def post(self, shared, prep_res, exec_res):
shared["query_embedding"] = exec_res
class RetrievalNode(Node):
"""检索节点"""
def prep(self, shared):
return (shared["query_embedding"],
shared["index"],
shared["embedded_chunks"])
def exec(self, inputs):
query_emb, index, chunks = inputs
top_indices, scores = search_similar(index, query_emb, top_k=3)
retrieved_chunks = []
for idx, score in zip(top_indices, scores):
chunk = chunks[idx]
retrieved_chunks.append({
"text": chunk["text"],
"filename": chunk["filename"],
"score": float(score)
})
return retrieved_chunks
def post(self, shared, prep_res, exec_res):
shared["retrieved_contexts"] = exec_res
class AnswerGenerationNode(Node):
"""答案生成节点"""
def prep(self, shared):
return shared["question"], shared["retrieved_contexts"]
def exec(self, inputs):
question, contexts = inputs
context_text = "\n\n".join([
f"文档片段 {i+1} (来源: {ctx['filename']}, 相似度: {ctx['score']:.3f}):\n{ctx['text']}"
for i, ctx in enumerate(contexts)
])
prompt = f"""
基于以下文档内容回答问题。如果文档中没有相关信息,请明确说明。
问题:{question}
相关文档内容:
{context_text}
请提供准确、详细的答案,并引用相关的文档来源。
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["answer"] = exec_res
# 创建 RAG 系统
def create_rag_system():
# 离线索引流程
chunker = DocumentChunkerNode()
embedder = EmbeddingNode()
indexer = IndexBuilderNode()
chunker >> embedder >> indexer
offline_flow = Flow(start=chunker)
# 在线查询流程
query_emb = QueryEmbeddingNode()
retriever = RetrievalNode()
generator = AnswerGenerationNode()
query_emb >> retriever >> generator
online_flow = Flow(start=query_emb)
return offline_flow, online_flow
# 使用示例
def test_rag_system():
# 准备文档数据
documents = [
("AI技术报告.txt", """
人工智能技术在过去十年中取得了重大突破。深度学习、自然语言处理和计算机视觉等领域都有显著进展。
特别是大型语言模型的出现,如GPT系列,为AI应用开辟了新的可能性。这些模型能够理解和生成人类语言,在文本摘要、翻译、代码生成等任务上表现出色。
然而,AI技术也面临一些挑战,包括数据隐私、算法偏见和计算资源消耗等问题。
"""),
("量子计算概述.txt", """
量子计算是一种利用量子力学原理进行信息处理的计算方式。与传统计算机使用二进制位不同,量子计算机使用量子位(qubits)。
量子位可以同时处于0和1的叠加状态,这使得量子计算机在处理某些特定问题时具有指数级的速度优势。
目前,量子计算在密码学、优化问题和药物发现等领域显示出巨大潜力。不过,构建稳定的量子计算机仍面临技术挑战。
""")
]
shared = {"documents": documents}
# 构建索引
offline_flow, online_flow = create_rag_system()
print("正在构建文档索引...")
offline_flow.run(shared)
print(f"索引构建完成,共处理 {len(shared['chunks'])} 个文档块")
# 回答问题
questions = [
"AI技术有哪些主要应用?",
"量子计算相比传统计算有什么优势?",
"区块链技术是什么?" # 文档中没有的内容
]
for question in questions:
print(f"\n问题:{question}")
shared["question"] = question
online_flow.run(shared)
print("检索到的相关内容:")
for i, ctx in enumerate(shared["retrieved_contexts"]):
print(f" {i+1}. {ctx['filename']} (相似度: {ctx['score']:.3f})")
print(f" {ctx['text'][:100]}...")
print(f"\n答案:{shared['answer']}")
print("-" * 80)
if __name__ == "__main__":
test_rag_system()
学习要点
- 两阶段架构:离线构建索引,在线检索生成
- 向量检索:将文本转换为向量,通过相似度匹配相关内容
- 上下文注入:将检索到的内容作为上下文提供给生成模型
- 可追溯性:答案可以追溯到具体的文档来源
实战项目
综合项目:智能内容创作平台
这个项目将综合运用多种设计模式,构建一个完整的智能内容创作系统,包括:
- Agent 模式用于内容策划
- RAG 模式用于资料检索
- MapReduce 模式用于并行创作
- Workflow 模式用于内容流水线
系统架构图
graph TB
subgraph "智能内容创作平台"
subgraph "策划阶段"
U[用户需求] --> PA[策划Agent]
PA -->|研究| RA[研究Agent]
PA -->|创意| CA[创意Agent]
RA --> KB[(知识库RAG)]
CA --> KB
end
subgraph "创作阶段"
PA --> BP[Batch并行创作]
BP --> W1[作者1: 大纲]
BP --> W2[作者2: 内容]
BP --> W3[作者3: 配图]
end
subgraph "整合阶段"
W1 --> WF[Workflow整合]
W2 --> WF
W3 --> WF
WF --> QA[质量审核Agent]
QA --> OUT[最终输出]
end
end
classDef agentStyle fill:#ffebee,stroke:#c62828,stroke-width:2px
classDef ragStyle fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
classDef batchStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef workflowStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
class PA,RA,CA,QA agentStyle
class KB ragStyle
class BP,W1,W2,W3 batchStyle
class WF workflowStyle
核心代码实现
import json
from typing import List, Dict, Any
class ContentPlanningAgent(Node):
"""内容策划代理"""
def prep(self, shared):
return shared["user_requirements"]
def exec(self, requirements):
prompt = f"""
作为内容策划专家,分析以下需求并制定创作计划:
需求:{requirements}
请提供结构化的策划方案:
```yaml
content_type: 文章类型
target_audience: 目标受众
key_topics:
- 主题1
- 主题2
research_areas:
- 研究方向1
- 研究方向2
action: research/creative/execute
```
"""
response = call_llm(prompt)
yaml_str = response.split("```yaml")[1].split("```")[0].strip()
return yaml.safe_load(yaml_str)
def post(self, shared, prep_res, exec_res):
shared["content_plan"] = exec_res
return exec_res["action"]
class ResearchAgent(Node):
"""研究代理"""
def prep(self, shared):
plan = shared["content_plan"]
return plan["research_areas"]
def exec(self, research_areas):
research_results = []
for area in research_areas:
# 这里可以接入真实的搜索API或RAG系统
prompt = f"针对'{area}'进行深度研究,提供关键信息和数据"
result = call_llm(prompt)
research_results.append({"area": area, "findings": result})
return research_results
def post(self, shared, prep_res, exec_res):
shared["research_results"] = exec_res
return "creative"
class CreativeAgent(Node):
"""创意代理"""
def prep(self, shared):
plan = shared["content_plan"]
research = shared["research_results"]
return plan, research
def exec(self, inputs):
plan, research = inputs
research_text = "\n".join([f"{r['area']}: {r['findings']}" for r in research])
prompt = f"""
基于策划方案和研究结果,生成创意内容框架:
策划方案:{json.dumps(plan, ensure_ascii=False)}
研究结果:{research_text}
请提供:
1. 内容大纲(详细章节结构)
2. 创作指导(每个章节的写作要点)
3. 素材建议(图片、图表、案例)
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["creative_framework"] = exec_res
return "execute"
class ParallelContentCreation(BatchFlow):
"""并行内容创作"""
def prep(self, shared):
# 为不同创作任务分配参数
tasks = [
{"role": "outline_writer", "task": "创建详细大纲"},
{"role": "content_writer", "task": "撰写主要内容"},
{"role": "visual_designer", "task": "设计视觉元素"}
]
return tasks
class ContentCreatorNode(Node):
"""内容创作节点"""
def prep(self, shared):
role = self.params["role"]
task = self.params["task"]
framework = shared["creative_framework"]
plan = shared["content_plan"]
return role, task, framework, plan
def exec(self, inputs):
role, task, framework, plan = inputs
if role == "outline_writer":
prompt = f"""
作为大纲编写专家,基于创意框架创建详细大纲:
创意框架:{framework}
内容计划:{json.dumps(plan, ensure_ascii=False)}
请创建结构化的内容大纲,包括:
- 标题层级
- 每节要点
- 预估字数
"""
elif role == "content_writer":
prompt = f"""
作为内容写作专家,基于创意框架撰写主要内容:
创意框架:{framework}
请撰写高质量的内容,注意:
- 逻辑清晰
- 表达生动
- 信息准确
"""
else: # visual_designer
prompt = f"""
作为视觉设计专家,基于创意框架设计视觉方案:
创意框架:{framework}
请提供视觉设计建议:
- 图片类型和风格
- 图表数据可视化方案
- 整体视觉布局
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
role = self.params["role"]
if "creation_results" not in shared:
shared["creation_results"] = {}
shared["creation_results"][role] = exec_res
class ContentIntegrationWorkflow(Flow):
"""内容整合工作流"""
def prep(self, shared):
return shared["creation_results"]
def post(self, shared, prep_res, exec_res):
# Flow的post方法,可以在这里进行整合后的处理
return "quality_check"
class QualityAssuranceAgent(Node):
"""质量保证代理"""
def prep(self, shared):
creation_results = shared["creation_results"]
original_plan = shared["content_plan"]
return creation_results, original_plan
def exec(self, inputs):
results, plan = inputs
combined_content = "\n\n".join([
f"【{role}】\n{content}"
for role, content in results.items()
])
prompt = f"""
作为质量审核专家,请评估以下创作内容:
原始需求:{json.dumps(plan, ensure_ascii=False)}
创作内容:
{combined_content}
请提供:
1. 质量评估(1-10分)
2. 具体建议
3. 是否需要修改(approve/revise)
"""
return call_llm(prompt)
def post(self, shared, prep_res, exec_res):
shared["quality_assessment"] = exec_res
# 简化处理,实际可以根据评估结果决定是否重新创作
return "approve"
class FinalOutputNode(Node):
"""最终输出节点"""
def prep(self, shared):
return shared["creation_results"], shared["quality_assessment"]
def exec(self, inputs):
results, assessment = inputs
# 整合所有内容
final_content = {
"outline": results.get("outline_writer", ""),
"content": results.get("content_writer", ""),
"visuals": results.get("visual_designer", ""),
"quality_score": assessment
}
return final_content
def post(self, shared, prep_res, exec_res):
shared["final_output"] = exec_res
# 组装完整的内容创作平台
def create_content_creation_platform():
# 策划阶段
planner = ContentPlanningAgent()
researcher = ResearchAgent()
creative = CreativeAgent()
# 并行创作阶段
creator_node = ContentCreatorNode()
parallel_creation = ParallelContentCreation(start=creator_node)
# 整合和质检阶段
qa_agent = QualityAssuranceAgent()
final_output = FinalOutputNode()
# 连接流程
planner - "research" >> researcher
planner - "creative" >> creative
planner - "execute" >> parallel_creation
researcher - "creative" >> creative
creative - "execute" >> parallel_creation
parallel_creation >> qa_agent
qa_agent - "approve" >> final_output
return Flow(start=planner)
# 使用示例
def demo_content_platform():
shared = {
"user_requirements": """
我需要创作一篇关于'人工智能在教育领域应用'的深度文章,
目标读者是教育工作者和技术管理人员。
文章需要包含现状分析、技术解读、案例研究和未来展望。
希望内容专业且易懂,篇幅约3000字。
"""
}
platform = create_content_creation_platform()
print("🚀 启动智能内容创作平台...")
platform.run(shared)
print("\n📋 策划方案:")
print(json.dumps(shared["content_plan"], ensure_ascii=False, indent=2))
print("\n🔍 研究结果:")
for result in shared["research_results"]:
print(f"- {result['area']}: {result['findings'][:100]}...")
print("\n💡 创意框架:")
print(shared["creative_framework"][:300] + "...")
print("\n✍️ 创作结果:")
for role, content in shared["creation_results"].items():
print(f"【{role}】: {content[:150]}...")
print("\n✅ 质量评估:")
print(shared["quality_assessment"])
print("\n🎯 最终输出已完成!")
if __name__ == "__main__":
demo_content_platform()
项目特点
-
多模式融合:
- Agent 模式处理策划和决策
- Batch 模式实现并行创作
- Workflow 模式管理整体流程
-
可扩展架构:
- 易于添加新的创作角色
- 支持不同类型的内容创作
- 可集成外部API和服务
-
质量控制:
- 多阶段审核机制
- 自动化质量评估
- 迭代优化支持
-
并行处理:
- 多个创作任务同时进行
- 提高整体创作效率
- 专业化分工协作
最佳实践总结
1. 设计原则
- 单一职责:每个 Node 只负责一个具体任务
- 松耦合:通过 shared store 实现数据解耦
- 可组合:Flow 可以嵌套和重用
- 故障隔离:合理使用重试和降级机制
2. 性能优化
- 批处理:对相似任务使用 BatchNode
- 并行处理:利用 AsyncParallelBatchNode 提升效率
- 缓存策略:为昂贵的计算添加缓存
- 资源管理:控制并发数量避免超过API限制
3. 可维护性
- 结构化数据:使用 YAML/JSON 格式化输入输出
- 日志记录:在关键节点添加详细日志
- 错误处理:提供有意义的错误信息和降级方案
- 文档化:为每个节点和流程编写清晰文档
4. 扩展建议
- 插件机制:通过配置文件动态加载不同的处理逻辑
- 监控告警:集成监控系统跟踪性能和错误
- A/B测试:支持不同策略的对比实验
- 版本管理:为模型和流程建立版本控制
通过掌握这些概念和实践,你已经具备了使用 PocketFlow 构建复杂 AI 应用的能力。框架的简洁性和灵活性将帮助你快速迭代和优化你的 AI 系统。