固定顺序调用#
在按 Python 中硬编码的顺序调用多个子函数的同时,(可选地)调用 LLM。
适用场景#
- 研究流水线:调研 → 找差距 → 生成想法
- 论文流水线:起草 → 评审 → 修改
- 数据流水线:采集 → 清洗 → 分析
- 任何步骤顺序事先已知的多步任务
设计要点#
- 编排函数写成普通的
Agentmethod - 按固定顺序调用多个子
Agentmethod llm()是可选的:可以跳过它(纯链式调用),也可以多次调用它 (每次调用都会创建一个llm子节点)- 数据通过普通 Python 变量在子函数之间流动
- 子 method 沿用调用方的 Runtime,步骤之间不传
runtime参数 - 一个函数既可以多次调用
llm(),也可以调用任意多个其他Agentmethod
示例:不调用 LLM,纯链式调用#
from openprogram import Agent
from openprogram.agentic_programming import llm
class ExampleAgent(Agent):
method_options = {
'research_pipeline': {'tool': True, 'input': {'task': {'description': 'Research topic.'}}},
}
def research_pipeline(self, task: str) -> dict:
"""Run the full research pipeline: survey, find gaps, generate ideas."""
survey = survey_topic(topic=task)
gaps = identify_gaps(survey=survey)
ideas = generate_ideas(gaps=gaps)
return {"survey": survey, "gaps": gaps, "ideas": ideas}
_example_agent = ExampleAgent()
research_pipeline = _example_agent.research_pipeline
示例:用一次 llm() 调用做汇总#
from openprogram import Agent
from openprogram.agentic_programming import llm
class ExampleAgent(Agent):
method_options = {
'research_pipeline': {'tool': True, 'input': {'task': {'description': 'Research topic.'}}},
}
def research_pipeline(self, task: str) -> str:
"""Run the full research pipeline and summarise the results."""
survey = survey_topic(topic=task)
gaps = identify_gaps(survey=survey)
ideas = generate_ideas(gaps=gaps)
return llm([
{"type": "text", "text": (
f"Survey:\n{survey}\n\n"
f"Gaps:\n{gaps}\n\n"
f"Ideas:\n{ideas}"
)},
])
_example_agent = ExampleAgent()
research_pipeline = _example_agent.research_pipeline
会话 DAG#
每次调用是一个节点;caller 边指向编排函数:
research_pipeline
├── survey_topic ← step 1
├── identify_gaps ← step 2
└── generate_ideas ← step 3
在步骤之间传递数据#
子函数通过 Python 变量彼此交接数据 —— 不涉及任何 LLM:
survey = survey_topic(topic=task)
gaps = identify_gaps(survey=survey)
survey_topic 的返回值直接作为 identify_gaps 的输入参数传入。
在步骤之间插入 Python 处理逻辑#
survey = survey_topic(topic=task)
# 中间穿插普通的 Python 处理
key_points = extract_key_points(survey)
filtered = [p for p in key_points if p["relevance"] > 0.5]
gaps = identify_gaps(survey="\n".join(filtered))
错误处理#
主要机制是异常传播:当子函数抛出异常时,其 DAG 节点会以
status='error' 记录,异常重新抛回到编排器中。在那里用普通的
try/except 捕获它:
try:
survey = survey_topic(topic=task)
except Exception as e:
return {"error": f"Survey failed: {e}"}
gaps = identify_gaps(survey=survey)
或者,如果子函数以带内方式上报失败(返回错误字符串而非抛出异常), 则检查其返回值:
survey = survey_topic(topic=task)
if not survey or "error" in survey.lower():
return {"error": "Survey failed", "survey": survey}
gaps = identify_gaps(survey=survey)
与“由 LLM 选择调用”的对比#
| 固定顺序调用 | 工具调用 / 下一步决策 | |
|---|---|---|
| 由谁决定调用顺序 | Python 代码 | LLM |
| 运行多少个子函数 | 若干个,全部运行 | 工具循环:跨多轮运行多个;决策菜单:仅一个 |
| 灵活性 | 固定流水线 | 随任务而变 |
Last updated · 2026-10-10