本系列文章用最朴素的方式从零构建一个生产级 AI Agent。不依赖 LangChain、不依赖 AutoGPT只用原生 API 和 Python。上一篇现在整个行业都在谈论 “AI Agent“https://blog.csdn.net/weixin_43499199/article/details/161593902?spm1001.2014.3001.5501核心观点一个工具 一个循环 一个 Agent。所有复杂的 Agent 能力都建立在这个最简单的循环之上。前言为什么 Agent Loop 是 AI 的 “操作系统”在大模型出现之前所有程序都是确定性的——你写什么代码它就做什么事。大模型带来了推理能力但它有一个致命缺陷它是一个纯函数。给它一个输入它输出一个结果然后就结束了。它不能自己读文件、不能自己跑代码、不能自己看报错、不能自己修正错误。没有循环你就是那个 Agent。你需要问大模型一个问题复制它的输出手动执行命令把执行结果再粘贴回去重复这个过程直到问题解决而 Agent Loop就是把你从这个循环里解放出来的那一行代码while True。这就是为什么我把它称为 AI 的 “操作系统”——它是模型与真实世界的第一道连接是所有智能行为的基础。问题大模型是 “缸中之脑”语言模型拥有强大的推理能力但它被关在一个玻璃盒子里。它能写出完美的 Python 代码但它不能运行这段代码它能告诉你如何修复一个 bug但它不能看到错误日志它能设计一个完整的项目结构但它不能创建任何文件它能解释 Git 命令的用法但它不能执行任何 Git 操作。没有与真实世界交互的能力大模型永远只是一个 “顾问”而不是一个 “执行者”。而绝大多数人使用大模型的方式就是自己充当那个 “手动循环”你提问 → 大模型回答 → 你执行 → 你把结果告诉大模型 → 大模型再回答 → ...这个过程枯燥、重复、容易出错而且效率极低。解决方案一个无限循环 一个退出条件解决这个问题的方法简单到令人难以置信加一个while循环。-------- ------- --------- | User | --- | LLM | --- | Tool | | prompt | | | | execute | -------- ------ -------- ^ | | tool_result | ---------------- (loop until stop_reason ! tool_use)这就是整个 Agent 的核心架构。没有任何复杂的概念没有任何多余的组件。工作原理把用户的问题发给大模型大模型决定是直接回答还是调用工具如果调用工具就执行工具把结果返回给大模型重复步骤 2-3直到大模型决定不再调用工具返回最终答案给用户就是这么简单。所有你听说过的复杂 Agent 框架本质上都是在这个循环上叠加各种优化和机制。完整实现30 行 Python 代码下面是一个完整可运行的 Agent 实现。它只有 30 行代码但它已经是一个真正的 AI Agent 了。前置准备首先安装 Anthropic SDK我们用 Claude 3.5 Sonnet 作为基础模型它的工具调用能力是目前最好的pipinstallanthropic然后设置你的 API 密钥exportANTHROPIC_API_KEYyour_api_key_here完整代码importosimportsubprocessfromanthropicimportAnthropic# 配置MODELclaude-3-5-sonnet-20240620SYSTEM_PROMPT 你是一个可以执行Bash命令的AI助手。 当用户要求你执行操作时使用bash工具来完成。 不要编造结果所有操作都必须通过工具执行。 执行完命令后根据输出结果回答用户的问题。 # 初始化客户端clientAnthropic(api_keyos.environ.get(ANTHROPIC_API_KEY))# 定义唯一的工具Bash执行器TOOLS[{name:bash,description:执行Bash命令并返回输出,input_schema:{type:object,properties:{command:{type:string,description:要执行的Bash命令}},required:[command]}}]defrun_bash(command):执行Bash命令并返回输出try:resultsubprocess.run(command,shellTrue,capture_outputTrue,textTrue,timeout30)returnfExit code:{result.returncode}\nStdout:\n{result.stdout}\nStderr:\n{result.stderr}exceptsubprocess.TimeoutExpired:returnError: Command timed out after 30 secondsdefagent_loop(query):Agent主循环messages[{role:user,content:query}]whileTrue:# 1. 调用大模型responseclient.messages.create(modelMODEL,systemSYSTEM_PROMPT,messagesmessages,toolsTOOLS,max_tokens8000)# 2. 把模型响应加入消息历史messages.append({role:assistant,content:response.content})# 3. 检查是否需要继续循环ifresponse.stop_reason!tool_use:# 模型不再调用工具返回最终答案returnresponse.content# 4. 执行所有工具调用results[]forblockinresponse.content:ifblock.typetool_use:print(f\n 执行命令:{block.input[command]})outputrun_bash(block.input[command])results.append({type:tool_result,tool_use_id:block.id,content:output})# 5. 把工具执行结果加入消息历史messages.append({role:user,content:results})# 测试运行if__name____main__:print( Agent 已启动输入 exit 退出)whileTrue:queryinput(\n )ifquery.lower()exit:breakresultagent_loop(query)print(\n 最终回答:)print(result[0].text)逐行解析Agent Loop 的工作原理让我们把这个循环拆开来看理解每一步到底在做什么。步骤 1初始化消息列表messages[{role:user,content:query}]消息列表是 Agent 的 “记忆”。它记录了整个对话的历史包括用户的问题、模型的回答和工具的执行结果。步骤 2调用大模型responseclient.messages.create(modelMODEL,systemSYSTEM_PROMPT,messagesmessages,toolsTOOLS,max_tokens8000)我们把完整的消息历史和工具定义一起发给大模型。大模型会根据上下文决定下一步做什么。步骤 3检查退出条件ifresponse.stop_reason!tool_use:returnresponse.content这是整个循环最关键的一行。stop_reason是大模型告诉我们它为什么停止生成内容如果是tool_use说明大模型想要调用工具我们需要继续循环如果是end_turn说明大模型已经完成了任务想要直接回答用户我们退出循环步骤 4执行工具调用forblockinresponse.content:ifblock.typetool_use:outputrun_bash(block.input[command])results.append(...)大模型可以在一次响应中调用多个工具。我们依次执行所有工具调用收集结果。步骤 5把结果返回给大模型messages.append({role:user,content:results})我们把工具执行的结果作为一条新的用户消息加入历史然后回到步骤 2继续循环。就是这样。这 30 行代码就是所有 AI Agent 的本质。我们到底添加了什么从一个普通的聊天机器人到一个真正的 Agent我们只添加了 4 个组件组件作用重要性while True循环让 Agent 可以自主地进行多步推理和操作⭐⭐⭐⭐⭐Bash 工具让 Agent 可以与真实世界交互⭐⭐⭐⭐⭐累积式消息列表让 Agent 拥有记忆知道自己之前做了什么⭐⭐⭐⭐stop_reason控制流让 Agent 可以自己决定什么时候结束任务⭐⭐⭐⭐重要提示后面的 11 个章节我们会在这个基础上添加更多的能力 —— 错误处理、并行工具调用、记忆管理、规划能力等等。但这个循环本身永远不会变。现在就试试把上面的代码保存为s01_agent_loop.py然后运行python s01_agent_loop.py试试这些 prompt看看你的第一个 Agent 能做什么基础操作创建一个叫hello.py的文件打印Hello, Agent! 列出当前目录下所有的Python文件 显示当前的Git分支 创建一个叫test的目录在里面创建3个文件a.txt, b.txt, c.txt稍微复杂一点的任务统计当前目录下所有Python文件的代码行数总和 查找所有包含agent关键词的文件 运行hello.py看看输出是什么 把test目录下的所有.txt文件压缩成test.zip真正展示 Agent 能力的任务我不小心把hello.py删了帮我恢复它 写一个Python脚本计算斐波那契数列的第100项然后运行它 检查当前系统的Python版本和pip版本 克隆一个GitHub仓库然后列出它的目录结构你会惊讶地发现这个只有 30 行代码的 Agent已经能完成绝大多数日常开发任务了。常见误区与注意事项为什么只用 Bash 一个工具因为 Bash 是最强大的工具。你可以用 Bash 做任何事 —— 读文件、写文件、运行程序、调用 API、管理系统等等。不需要为每一个操作定义单独的工具。Agent 会执行危险命令吗是的。所以永远不要用 root 权限运行 Agent也不要在生产环境中直接使用这个简单版本。后面的章节我们会添加安全沙箱和命令审核机制。为什么用 Claude 而不是 GPT-4Claude 3.5 Sonnet 的工具调用能力目前是业界最好的。它更擅长理解什么时候需要调用工具什么时候可以直接回答。当然你也可以很容易地把代码改成使用 OpenAI API。Agent 会陷入无限循环吗有可能。在后面的章节我们会添加最大循环次数限制和超时机制。总结在这一章我们用 30 行代码实现了一个真正的 AI Agent。我们没有使用任何复杂的框架没有引入任何抽象概念。我们只是给大模型加了一个循环让它可以自己执行命令自己看结果自己修正错误。这就是 Agent 的本质一个能够自主地与环境交互直到完成目标的程序。所有复杂的 Agent 能力 —— 规划、记忆、推理、工具使用 —— 都是建立在这个最简单的循环之上的。下一章预告S02工具的使用加一个工具只加一个 handler
【Agent 从零到一】S01:The Agent Loop —— 30 行代码实现一个真正的 AI Agent
本系列文章用最朴素的方式从零构建一个生产级 AI Agent。不依赖 LangChain、不依赖 AutoGPT只用原生 API 和 Python。上一篇现在整个行业都在谈论 “AI Agent“https://blog.csdn.net/weixin_43499199/article/details/161593902?spm1001.2014.3001.5501核心观点一个工具 一个循环 一个 Agent。所有复杂的 Agent 能力都建立在这个最简单的循环之上。前言为什么 Agent Loop 是 AI 的 “操作系统”在大模型出现之前所有程序都是确定性的——你写什么代码它就做什么事。大模型带来了推理能力但它有一个致命缺陷它是一个纯函数。给它一个输入它输出一个结果然后就结束了。它不能自己读文件、不能自己跑代码、不能自己看报错、不能自己修正错误。没有循环你就是那个 Agent。你需要问大模型一个问题复制它的输出手动执行命令把执行结果再粘贴回去重复这个过程直到问题解决而 Agent Loop就是把你从这个循环里解放出来的那一行代码while True。这就是为什么我把它称为 AI 的 “操作系统”——它是模型与真实世界的第一道连接是所有智能行为的基础。问题大模型是 “缸中之脑”语言模型拥有强大的推理能力但它被关在一个玻璃盒子里。它能写出完美的 Python 代码但它不能运行这段代码它能告诉你如何修复一个 bug但它不能看到错误日志它能设计一个完整的项目结构但它不能创建任何文件它能解释 Git 命令的用法但它不能执行任何 Git 操作。没有与真实世界交互的能力大模型永远只是一个 “顾问”而不是一个 “执行者”。而绝大多数人使用大模型的方式就是自己充当那个 “手动循环”你提问 → 大模型回答 → 你执行 → 你把结果告诉大模型 → 大模型再回答 → ...这个过程枯燥、重复、容易出错而且效率极低。解决方案一个无限循环 一个退出条件解决这个问题的方法简单到令人难以置信加一个while循环。-------- ------- --------- | User | --- | LLM | --- | Tool | | prompt | | | | execute | -------- ------ -------- ^ | | tool_result | ---------------- (loop until stop_reason ! tool_use)这就是整个 Agent 的核心架构。没有任何复杂的概念没有任何多余的组件。工作原理把用户的问题发给大模型大模型决定是直接回答还是调用工具如果调用工具就执行工具把结果返回给大模型重复步骤 2-3直到大模型决定不再调用工具返回最终答案给用户就是这么简单。所有你听说过的复杂 Agent 框架本质上都是在这个循环上叠加各种优化和机制。完整实现30 行 Python 代码下面是一个完整可运行的 Agent 实现。它只有 30 行代码但它已经是一个真正的 AI Agent 了。前置准备首先安装 Anthropic SDK我们用 Claude 3.5 Sonnet 作为基础模型它的工具调用能力是目前最好的pipinstallanthropic然后设置你的 API 密钥exportANTHROPIC_API_KEYyour_api_key_here完整代码importosimportsubprocessfromanthropicimportAnthropic# 配置MODELclaude-3-5-sonnet-20240620SYSTEM_PROMPT 你是一个可以执行Bash命令的AI助手。 当用户要求你执行操作时使用bash工具来完成。 不要编造结果所有操作都必须通过工具执行。 执行完命令后根据输出结果回答用户的问题。 # 初始化客户端clientAnthropic(api_keyos.environ.get(ANTHROPIC_API_KEY))# 定义唯一的工具Bash执行器TOOLS[{name:bash,description:执行Bash命令并返回输出,input_schema:{type:object,properties:{command:{type:string,description:要执行的Bash命令}},required:[command]}}]defrun_bash(command):执行Bash命令并返回输出try:resultsubprocess.run(command,shellTrue,capture_outputTrue,textTrue,timeout30)returnfExit code:{result.returncode}\nStdout:\n{result.stdout}\nStderr:\n{result.stderr}exceptsubprocess.TimeoutExpired:returnError: Command timed out after 30 secondsdefagent_loop(query):Agent主循环messages[{role:user,content:query}]whileTrue:# 1. 调用大模型responseclient.messages.create(modelMODEL,systemSYSTEM_PROMPT,messagesmessages,toolsTOOLS,max_tokens8000)# 2. 把模型响应加入消息历史messages.append({role:assistant,content:response.content})# 3. 检查是否需要继续循环ifresponse.stop_reason!tool_use:# 模型不再调用工具返回最终答案returnresponse.content# 4. 执行所有工具调用results[]forblockinresponse.content:ifblock.typetool_use:print(f\n 执行命令:{block.input[command]})outputrun_bash(block.input[command])results.append({type:tool_result,tool_use_id:block.id,content:output})# 5. 把工具执行结果加入消息历史messages.append({role:user,content:results})# 测试运行if__name____main__:print( Agent 已启动输入 exit 退出)whileTrue:queryinput(\n )ifquery.lower()exit:breakresultagent_loop(query)print(\n 最终回答:)print(result[0].text)逐行解析Agent Loop 的工作原理让我们把这个循环拆开来看理解每一步到底在做什么。步骤 1初始化消息列表messages[{role:user,content:query}]消息列表是 Agent 的 “记忆”。它记录了整个对话的历史包括用户的问题、模型的回答和工具的执行结果。步骤 2调用大模型responseclient.messages.create(modelMODEL,systemSYSTEM_PROMPT,messagesmessages,toolsTOOLS,max_tokens8000)我们把完整的消息历史和工具定义一起发给大模型。大模型会根据上下文决定下一步做什么。步骤 3检查退出条件ifresponse.stop_reason!tool_use:returnresponse.content这是整个循环最关键的一行。stop_reason是大模型告诉我们它为什么停止生成内容如果是tool_use说明大模型想要调用工具我们需要继续循环如果是end_turn说明大模型已经完成了任务想要直接回答用户我们退出循环步骤 4执行工具调用forblockinresponse.content:ifblock.typetool_use:outputrun_bash(block.input[command])results.append(...)大模型可以在一次响应中调用多个工具。我们依次执行所有工具调用收集结果。步骤 5把结果返回给大模型messages.append({role:user,content:results})我们把工具执行的结果作为一条新的用户消息加入历史然后回到步骤 2继续循环。就是这样。这 30 行代码就是所有 AI Agent 的本质。我们到底添加了什么从一个普通的聊天机器人到一个真正的 Agent我们只添加了 4 个组件组件作用重要性while True循环让 Agent 可以自主地进行多步推理和操作⭐⭐⭐⭐⭐Bash 工具让 Agent 可以与真实世界交互⭐⭐⭐⭐⭐累积式消息列表让 Agent 拥有记忆知道自己之前做了什么⭐⭐⭐⭐stop_reason控制流让 Agent 可以自己决定什么时候结束任务⭐⭐⭐⭐重要提示后面的 11 个章节我们会在这个基础上添加更多的能力 —— 错误处理、并行工具调用、记忆管理、规划能力等等。但这个循环本身永远不会变。现在就试试把上面的代码保存为s01_agent_loop.py然后运行python s01_agent_loop.py试试这些 prompt看看你的第一个 Agent 能做什么基础操作创建一个叫hello.py的文件打印Hello, Agent! 列出当前目录下所有的Python文件 显示当前的Git分支 创建一个叫test的目录在里面创建3个文件a.txt, b.txt, c.txt稍微复杂一点的任务统计当前目录下所有Python文件的代码行数总和 查找所有包含agent关键词的文件 运行hello.py看看输出是什么 把test目录下的所有.txt文件压缩成test.zip真正展示 Agent 能力的任务我不小心把hello.py删了帮我恢复它 写一个Python脚本计算斐波那契数列的第100项然后运行它 检查当前系统的Python版本和pip版本 克隆一个GitHub仓库然后列出它的目录结构你会惊讶地发现这个只有 30 行代码的 Agent已经能完成绝大多数日常开发任务了。常见误区与注意事项为什么只用 Bash 一个工具因为 Bash 是最强大的工具。你可以用 Bash 做任何事 —— 读文件、写文件、运行程序、调用 API、管理系统等等。不需要为每一个操作定义单独的工具。Agent 会执行危险命令吗是的。所以永远不要用 root 权限运行 Agent也不要在生产环境中直接使用这个简单版本。后面的章节我们会添加安全沙箱和命令审核机制。为什么用 Claude 而不是 GPT-4Claude 3.5 Sonnet 的工具调用能力目前是业界最好的。它更擅长理解什么时候需要调用工具什么时候可以直接回答。当然你也可以很容易地把代码改成使用 OpenAI API。Agent 会陷入无限循环吗有可能。在后面的章节我们会添加最大循环次数限制和超时机制。总结在这一章我们用 30 行代码实现了一个真正的 AI Agent。我们没有使用任何复杂的框架没有引入任何抽象概念。我们只是给大模型加了一个循环让它可以自己执行命令自己看结果自己修正错误。这就是 Agent 的本质一个能够自主地与环境交互直到完成目标的程序。所有复杂的 Agent 能力 —— 规划、记忆、推理、工具使用 —— 都是建立在这个最简单的循环之上的。下一章预告S02工具的使用加一个工具只加一个 handler