状态:循环之间靠什么传递
对应清单 9.1 · 01_research_state_plan.py
整个文件只有三个 Pydantic 类。没有 main()、没有
asyncio.run、没有 __main__——
python 01_research_state_plan.py 跑它,屏幕上什么都不会出现。
它是给后面的文件抄的骨架,也是给书里排版用的。
from pydantic import BaseModel, Field
class SubTopic(BaseModel):
"""研究计划里的一个子话题。"""
name: str
status: str = "pending" # pending(待办)| in_progress(进行中)| complete(已完成)
notes: str = ""
class ResearchPlan(BaseModel):
"""指导整个研究过程的战略计划。"""
sub_topics: list[SubTopic] = Field(default_factory=list)
strategy_notes: str = ""
@property
def progress_summary(self) -> str:
if not self.sub_topics:
return "还没有计划"
total = len(self.sub_topics)
complete = sum(1 for st in self.sub_topics
if st.status == "complete")
in_progress = sum(1 for st in self.sub_topics
if st.status == "in_progress")
return (f"{complete}/{total} 已完成,"
f"{in_progress} 进行中")
class ResearchState(BaseModel):
goal: str = ""
findings: list[str] = Field(default_factory=list)
sources_consulted: list[str] = Field(default_factory=list)
follow_up_questions: list[str] = Field(default_factory=list)
plan: ResearchPlan = Field(default_factory=ResearchPlan)
iteration_count: int = 0
max_iterations: int = 10
status: str = "in_progress"
@property
def should_continue(self) -> bool:
# ↓ 这就是整章的终止门:三个条件缺一不可
return (
self.status == "in_progress"
and self.iteration_count < self.max_iterations
and len(self.follow_up_questions) > 0
)
前八章你从来不用管这个——因为跑一次就结束了,没有「之间」。 一旦循环起来,每一轮的产出必须活到下一轮:查到了什么、 还有哪些问题没查、计划进行到哪了。
注意 to_context() 这个方法(上面省略了)——
它把整个状态转成字符串塞回提示词。这就是循环的真相:
模型本身没有记忆,是你每轮把状态重新讲给它听。
所谓「智能体在推进研究」,实际是你在维护一个状态机,
每轮请模型看一眼、给点更新。