嘿,各位未来的“AI架构师”,我是元哥。
上回书咱们聊明白了,“上下文工程”是AI Agent的灵魂。理论讲了一大堆,大家肯定手痒了:“元哥,别光说不练啊,到底咋搞?”
好!今天,咱们就来一场真刀真枪的“深度潜航”!不扯理论,只上实战。元哥将用一个完整的Python代码示例,手把手带你,从零开始,打造一个能帮你读万卷书、做深度研究的“研究型AI Agent”。
注意: 下面的代码为了便于理解,省略了真实的LLM调用,用“模拟函数”代替。但它完整地展示了Agent的思考框架和运行逻辑,这才是精髓!
第一步:定义目标和武器库
我们的目标: 打造一个Agent,它能根据我们指定的几个本地文档,回答一个综合性的问题。
场景: 假设我们有两个本地文件,doc1.txt 和 doc2.txt,里面分别记录了关于RAG技术的优点和缺点。我们要让Agent回答:“请基于'doc1.txt'和'doc2.txt',总结RAG技术的优缺点。”
Agent的武器库(工具箱): 我们先用Python定义好Agent能使用的工具。
# --- 模拟工具箱 ---
def read_file_content(path: str) -> str:
"""读取指定文件的内容。"""
print(f"【工具调用:读取文件 {path}】")
# 在真实世界里,这里会真的去读文件
# 我们用假数据代替
if path == 'doc1.txt':
return "RAG的优点:1. 知识库可以随时更新,解决了LLM知识截止的问题。 2. 因为答案有据可循,大大减少了模型一本正经胡说八道的‘幻觉’现象。"
elif path == 'doc2.txt':
return "RAG的缺点:1. 检索的质量很大程度上决定了最终生成答案的质量,所谓‘垃圾进,垃圾出’。 2. 检索回来的文档片段和原始问题如何优雅地整合,是一个技术挑战。"
else:
return "错误:文件未找到。"
def synthesize_answer(information: list, question: str) -> str:
"""根据一系列信息,综合成最终答案。"""
print(f"【工具调用:综合信息回答 ‘{question}’】")
# 这里的核心是调用LLM来做最终的“总结陈词”
info_str = "\n".join(information)
# final_prompt = f"请基于以下信息:\n{info_str}\n\n来回答问题:{question}"
# return llm(final_prompt)
# 我们用模拟输出来代替
return f"综合分析,RAG技术的优点是知识可更新、减少幻觉;缺点是依赖检索质量、整合有挑战。"
# 我们还需要一个特殊的“结束”工具
def finish(final_answer: str) -> str:
"""任务完成,输出最终答案。"""
print("【任务完成】")
return final_answer
第二步:设计Agent的“大脑”和“工作手册”
接下来,我们用“分层上下文”的思想,来设计Agent的核心Prompt。这就像给它一本清晰的《工作手册》。
# --- Agent的核心Prompt设计 ---
# 1. 系统上下文 (System Layer) - Agent的灵魂和世界观
SYSTEM_PROMPT = """你是一个顶级的AI研究员。你的任务是根据用户的提问和指定的文档,给出一个全面、客观的回答。
你必须通过“思考”来规划步骤,然后选择合适的“行动”(工具调用)来执行。
你的行动必须是以下格式之一:
- `read_file_content(path: '文件名')`
- `synthesize_answer(information: [信息列表], question: '问题')`
- `finish(final_answer: '你的最终答案')`
"""
# 2. 任务上下文 (Task Layer) - 当前的具体任务
USER_QUESTION = "请基于 'doc1.txt' 和 'doc2.txt',总结RAG技术的优缺点。"
# 记忆与草稿纸 (Memory/Scratchpad) 将在运行中动态构建
这份“手册”告诉了Agent:我是谁?(研究员),我最终要干什么?(回答用户问题),我能用什么武器?(工具列表),我该如何行动?(思考-行动格式)。
第三步:构建Agent的“主循环”
现在,万事俱备,我们来构建Agent的核心运行逻辑。它将遵循ReAct模式,在“思考→行动→观察”的循环中,一步步完成任务。
# --- Agent的主循环 ---
class ResearchAgent:
def __init__(self, goal):
self.goal = goal
self.scratchpad = "" # 记忆与草稿纸,用于记录每一步的观察
self.tools = {
"read_file_content": read_file_content,
"synthesize_answer": synthesize_answer,
"finish": finish
}
def run(self):
while True:
# 1. 构建完整的Prompt (四层上下文的组合)
prompt = self._build_prompt()
print("--- 向LLM发送的完整Prompt ---" + prompt + "--------------------------")
# 2. 调用LLM进行思考和行动决策 (这里我们手动模拟LLM的输出)
llm_output = self._mock_llm_call(self.scratchpad)
print(f"--- LLM的输出 ---
{llm_output}\n--------------------")
# 3. 解析LLM的输出,分离出“思考”和“行动”
thought, action_str = self._parse_output(llm_output)
print(f"思考: {thought}")
# 4. 执行行动
if action_str.startswith("finish"):
# 如果是结束指令,就输出结果并终止循环
final_answer = eval(action_str.replace("finish", ""))[0]
print(f"\n最终答案:{final_answer}")
break
observation = self._execute_action(action_str)
print(f"观察: {observation}\n")
# 5. 更新“草稿纸”,为下一步思考做准备
self.scratchpad += f"\n思考: {thought}\n行动: {action_str}\n观察: {observation}"
def _build_prompt(self):
"""构建发送给LLM的完整Prompt"""
return f"{SYSTEM_PROMPT}\n\n# 记忆与草稿纸\n{self.scratchpad}\n\n# 当前任务\n用户问题: {self.goal}"
def _execute_action(self, action_str):
"""执行工具调用"""
try:
# 解析`tool_name(args)`格式
tool_name = action_str.split("(")[0]
args_str = action_str[len(tool_name):]
# 安全地执行函数字符串
return self.tools[tool_name](**eval("dict" + args_str))
except Exception as e:
return f"行动执行错误: {e}"
def _parse_output(self, llm_output):
"""解析LLM输出,分离思考和行动"""
thought = llm_output.split("行动:")[0].strip()
action_str = llm_output.split("行动:")[1].strip()
return thought, action_str
def _mock_llm_call(self, scratchpad):
"""模拟LLM的思考过程,这是Agent智能的核心"""
if "doc1.txt" not in scratchpad:
return "思考: 我需要先读取第一个文档'doc1.txt'来找RAG的优点。\n行动: read_file_content(path='doc1.txt')"
elif "doc2.txt" not in scratchpad:
return "思考: 我已经有了关于优点的信息。现在我需要读取第二个文档'doc2.txt'来找RAG的缺点。\n行动: read_file_content(path='doc2.txt')"
else:
return "思考: 我已经收集了所有文档中关于优缺点的信息。现在是时候把它们整合起来,形成最终答案了。\n行动: synthesize_answer(information=['RAG的优点...', 'RAG的缺点...'], question='总结RAG技术的优缺点')"
# --- 运行Agent ---
if __name__ == "__main__":
agent = ResearchAgent(USER_QUESTION)
agent.run()
当你运行这段代码,你会清晰地看到一个Agent是如何一步步思考、行动、观察,并最终完成你交给它的复杂研究任务的。
元哥小结
老铁们,感觉怎么样?
今天,我们没有讲太多花哨的理论,而是完整地走了一遍“构建-思考-执行”的全流程,并给出了一个可以跑起来(虽然是模拟的)的代码框架。我们通过“分层上下文”赋予了Agent清晰的“世界观”,通过定义工具给了它行动的“手脚”,最后通过ReAct的思考模式,让它“活”了起来。
这就是“上下文工程”的魅力。它不是一个单一的技巧,而是一套设计哲学,一套将我们的目标、规则和资源,有效地传递给AI,并引导它完成复杂任务的系统工程。
我们今天的Agent很强大,但它的“工作手册”(分层上下文)还是需要我们人工去精心设计的。有没有可能,让Agent自己去管理和维护这个“工作台”,甚至根据任务动态调整自己的“思考架构”?
当然有!
下一期,也是我们AI Agent系列的最后一期,元哥将带大家仰望星空,聊一聊更前沿的、拥有“元认知”能力的**“深度智能体”(Deep Agents)**!这可能是通向通用人工智能(AGI)的最后一块拼图。千万别错过!
【引用说明】 本文的创作灵感和核心知识点来源于《Prompt Engineering Guide》网站。
- Context Engineering Deep Dive: Building a Deep Research Agent: www.promptingguide.ai/agents/cont…
- Context Engineering Guide: www.promptingguide.ai/guides/cont…
大家也可微信搜索“极客纪元”并关注我,获得更多分享。