当前位置: 首页 > news >正文

50行Python手搓一个原生AI Agent:彻底看懂智能体的本质


你是不是也被各种AI Agent框架搞晕了?LangChain、CrewAI、AutoGPT… 每个框架都有几百个类、几千行代码,文档看到头大,却始终没搞懂Agent到底是什么。

今天我要告诉你一个真相:AI Agent的核心,其实就是一个while循环。所有复杂的框架,本质上都是在这个循环外面包了一层又一层的抽象。只要你理解了这个最基本的循环,你就能看懂所有Agent框架的源码,甚至能自己写出比框架更灵活的实现。

这篇文章我会用纯原生Python,不依赖任何Agent框架,只用50行代码,带你实现一个完整的、具备工具调用能力的AI Agent。你会亲眼看到,所谓的"智能体",到底是怎么工作的。

AI Agent的本质:一个循环而已

在写代码之前,我们先搞清楚一个最核心的问题:什么是AI Agent?

很多人会给你讲一堆高大上的概念:感知层、认知层、执行层、记忆系统、规划模块… 这些都对,但都太抽象了。

从工程实现的角度看,AI Agent = 大语言模型 + 工具集 + 一个无限循环

这个循环就是著名的"ReAct循环":

  1. 思考(Thought):模型根据当前状态,决定下一步要做什么
  2. 行动(Action):调用对应的工具执行操作
  3. 观察(Observation):获取工具执行的结果
  4. 重复:把结果返回给模型,继续下一轮思考

就是这么简单。所有复杂的Agent系统,都是在这个基础循环上扩展出来的。

我画了一张最简单的Agent架构图,你一看就懂:

用户输入目标

初始化消息历史

是否完成任务?

调用大模型思考

需要调用工具?

解析工具调用参数

执行工具函数

将结果添加到消息历史

生成最终回答

返回给用户

看到了吗?整个流程没有任何神秘的地方。大模型只是这个循环中的一个"思考"环节,它的作用就是判断:我现在需要调用什么工具?或者我已经有足够的信息回答用户了吗?

50行代码实现完整AI Agent

好了,理论讲完了,现在开始写代码。我们只需要安装一个依赖:openaiSDK。

pipinstallopenai python-dotenv

然后创建一个simple_agent.py文件,把下面的代码复制进去。我数过了,去掉空行和注释,正好50行左右。

importosimportjsonfromdotenvimportload_dotenvfromopenaiimportOpenAI# 加载环境变量load_dotenv()client=OpenAI(api_key=os.getenv("OPENAI_API_KEY"))MODEL="gpt-4o-mini"# 用最便宜的模型就行,效果足够好# 定义工具函数:这就是Agent的"手脚"defget_weather(city:str)->str:"""查询指定城市的天气"""# 这里模拟API调用,实际项目中替换成真实的天气APIweather_data={"北京":"晴天,25-32℃,微风","上海":"多云,23-28℃,东南风3级","深圳":"雷阵雨,26-30℃,南风4级"}returnweather_data.get(city,f"抱歉,没有找到{city}的天气信息")defget_current_time()->str:"""获取当前系统时间"""fromdatetimeimportdatetimereturndatetime.now().strftime("%Y年%m月%d日 %H:%M:%S")defcalculate(expression:str)->str:"""执行数学计算"""try:returnf"计算结果:{eval(expression)}"exceptExceptionase:returnf"计算错误:{str(e)}"# 工具定义:告诉模型有哪些工具可用TOOLS=[{"type":"function","function":{"name":"get_weather","description":"查询指定城市的天气情况","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名称,例如:北京"}},"required":["city"]}}},{"type":"function","function":{"name":"get_current_time","description":"获取当前系统时间","parameters":{"type":"object","properties":{}}}},{"type":"function","function":{"name":"calculate","description":"执行数学计算,支持加减乘除和括号","parameters":{"type":"object","properties":{"expression":{"type":"string","description":"数学表达式,例如:123 * 456"}},"required":["expression"]}}}]# 工具映射:方便根据函数名找到对应的函数tool_map={"get_weather":get_weather,"get_current_time":get_current_time,"calculate":calculate}defrun_agent(user_query:str)->str:"""运行AI Agent的主函数"""messages=[{"role":"system","content":"你是一个有用的AI助手。你可以使用提供的工具来帮助用户解决问题。如果需要调用工具,请使用函数调用格式。当你有足够的信息回答用户问题时,请直接给出最终答案,不要继续调用工具。"},{"role":"user","content":user_query}]whileTrue:# 调用大模型思考response=client.chat.completions.create(model=MODEL,messages=messages,tools=TOOLS,tool_choice="auto")message=response.choices[0].message messages.append(message)# 如果模型不需要调用工具,直接返回回答ifnotmessage.tool_calls:returnmessage.content# 执行所有工具调用fortool_callinmessage.tool_calls:function_name=tool_call.function.name function_args=json.loads(tool_call.function.arguments)print(f"\n🤖 Agent正在调用工具:{function_name}({function_args})")# 调用对应的工具函数function_response=tool_map[function_name](**function_args)print(f"📦 工具返回结果:{function_response}")# 将工具结果添加到消息历史messages.append({"role":"tool","tool_call_id":tool_call.id,"name":function_name,"content":function_response})# 测试一下if__name__=="__main__":print("="*50)print("50行Python实现的AI Agent")print("="*50)whileTrue:user_input=input("\n请输入你的问题(输入'退出'结束): ")ifuser_input.lower()in["退出","exit","quit"]:breakprint("\n🧠 Agent正在思考中...")result=run_agent(user_input)print(f"\n✅ Agent回答:{result}")

代码逐行解析

别看代码短,它包含了一个完整AI Agent的所有核心组件:

1. 工具定义(第13-35行)

这是Agent的"手脚"。我们定义了三个简单的工具:查询天气、获取时间、数学计算。每个工具都有清晰的描述和参数定义,大模型会根据这些描述来决定什么时候调用哪个工具。

2. 工具映射(第68-72行)

一个简单的字典,把函数名映射到实际的函数对象。这样当模型说"我要调用get_weather函数"的时候,我们就能快速找到对应的函数并执行。

3. 主循环(第85-112行)

这就是Agent的心脏!整个run_agent函数就是一个无限循环:

  • 第89-95行:调用大模型,让它根据当前的消息历史思考下一步
  • 第99-100行:如果模型说"我不需要工具了,我可以回答了",就直接返回结果
  • 第103-111行:如果模型需要调用工具,就解析参数,执行工具函数,然后把结果返回给模型
  • 然后循环继续,直到模型认为任务完成

就是这么简单!没有任何复杂的抽象,没有任何黑箱操作。每一步你都能看得清清楚楚。

运行效果演示

现在我们来运行一下这个Agent,看看它的表现:

================================================== 50行Python实现的AI Agent ================================================== 请输入你的问题(输入'退出'结束): 现在几点了? 🧠 Agent正在思考中... 🤖 Agent正在调用工具: get_current_time({}) 📦 工具返回结果: 2026年05月28日 19:52:37 ✅ Agent回答: 现在的时间是2026年05月28日 19:52:37。 请输入你的问题(输入'退出'结束): 北京今天天气怎么样?适合穿什么衣服? 🧠 Agent正在思考中... 🤖 Agent正在调用工具: get_weather({'city': '北京'}) 📦 工具返回结果: 晴天,25-32℃,微风 ✅ Agent回答: 北京今天是晴天,气温在25-32℃之间,有微风。建议穿短袖、短裤等轻薄透气的衣服,注意防晒。 请输入你的问题(输入'退出'结束): 1234乘以5678等于多少?再加上9876呢? 🧠 Agent正在思考中... 🤖 Agent正在调用工具: calculate({'expression': '1234 * 5678'}) 📦 工具返回结果: 计算结果: 7006652 🤖 Agent正在调用工具: calculate({'expression': '7006652 + 9876'}) 📦 工具返回结果: 计算结果: 7016528 ✅ Agent回答: 1234乘以5678等于7006652,再加上9876等于7016528。

看到了吗?这个只有50行代码的Agent,已经能够:

  • 自主判断是否需要调用工具
  • 正确解析工具参数
  • 连续调用多个工具完成复杂任务
  • 根据工具返回的结果生成自然语言回答

这和你用LangChain写出来的Agent,本质上没有任何区别。

为什么我建议你先写原生实现

很多人一上来就用LangChain,结果遇到问题根本不知道怎么调试。比如Agent突然不调用工具了,或者调用了错误的工具,你根本不知道是提示词的问题,还是框架的问题,还是模型本身的问题。

但是如果你先写过这个原生的实现,你就会明白:

  • 工具调用本质上就是模型输出了一个特定格式的JSON
  • 消息历史是Agent唯一的"记忆"
  • 框架所谓的"AgentExecutor",其实就是一个while循环

当你理解了这些本质之后,再去看任何Agent框架的源码,都会觉得一目了然。而且在实际项目中,很多时候原生实现比框架更灵活,性能更好,也更容易调试。

扩展方向:从50行到生产级

这个50行的Agent虽然简单,但它是一个完整的骨架。你可以在这个基础上,很容易地扩展出各种高级功能:

  1. 增加更多工具:比如网页搜索、文件读写、数据库查询、发送邮件等
  2. 增加记忆系统:用向量数据库存储长期记忆,实现上下文感知
  3. 增加规划能力:让Agent先把复杂任务拆解成步骤,再一步步执行
  4. 增加错误处理:处理工具调用失败、模型输出格式错误等情况
  5. 增加流式输出:让Agent的回答能够实时显示给用户
  6. 增加多轮对话:支持用户和Agent进行连续的对话

总结

AI Agent不是什么神秘的黑科技,它的核心就是一个"思考-行动-观察"的循环。所有复杂的框架,都是在这个循环的基础上构建起来的。

通过这50行代码,我希望你能真正理解Agent的本质。不要被各种高大上的概念和复杂的框架吓倒。编程的真谛,就是把复杂的问题拆解成简单的步骤,然后用代码一步步实现。

现在你已经有了一个可以工作的Agent骨架,接下来就尽情发挥你的想象力,用它来解决你自己的问题吧。

http://www.jsqmd.com/news/908393/

相关文章:

  • 高强度螺栓怎么选?从强度等级到应用场景,六月上海紧固件专业展
  • Smoothieware固件配置项探秘:手把手教你通过Code Review定位隐藏参数(如mm_per_arc_segment)
  • 搞定7nm DRC收敛:一份给Innovus和ICC2用户的联合调试备忘录
  • AI时代数据管道设计:从ETL到MLOps的现代化实践
  • MATLAB机器人控制器仿真代码包:从建模、设计到响应验证的一站式实现
  • 从关键词匹配到任务理解:Agent 意图识别的五代技术演进
  • 如何快速掌握BepInEx:Unity游戏模组开发的终极框架指南
  • 26个摄影实战故事:从新手到高手的避坑指南与创作心法
  • 开源语音识别模型:媲美谷歌级性能的本地化部署方案
  • 2026年4月目前靠谱的变压器定制推荐,龙门架电力构架/四管塔避雷塔/独立避雷针/三柱塔避雷针,变压器来图加工厂家销售 - 品牌推荐师
  • BepInEx终极指南:Unity游戏插件框架的完整安装与配置
  • 从抓包看本质:Wireshark深度解读TCP报文头每个字段的含义与实战作用
  • SVG 参考手册
  • 别再靠猜了!用SystemView+FreeRTOS实时‘看透’你的任务调度(保姆级配置避坑)
  • 【YFIOs】用C#开发硬件之GPIO操作
  • 基于Whisper、Llama 2与Bark构建本地离线语音助手实战指南
  • AI应用的用户体验设计:从用户研究到迭代
  • 术语俗话 --- 什么是类C代码
  • Uber 4 个月烧光 2026 全年 AI 预算:人均月账单 $500-$2000,企业 token 计费失控的第一个公开样本
  • 如何用 ChatGPT 提升学习指导效率?完整实现指南
  • 体育科技革命:从数据采集到AI分析,技术如何重塑竞技体育
  • Gemini多语言翻译质量深度拆解(中/日/阿/印地语实测盲区大曝光)
  • NVIDIA Profile Inspector终极指南:5个步骤解决显卡驱动兼容性难题
  • 微服务间的远程接口调用:OpenFeign 的使用
  • GAMP程序太老了?手把手教你修改源码,让北斗三号PPP定位精度起飞
  • 华硕笔记本终极优化指南:5个G-Helper核心功能让电脑重获新生
  • 量化投资基石:10大机器学习股票数据集选型与实战指南
  • ESPI协议详解:单线、双线、四线模式怎么选?服务器BMC带外管理实战
  • 鸿蒙数学 108 篇 第二十八篇:计数体系完整推演
  • ArcSWAT建模新手避坑指南:你的土壤参数SOL_AWC算对了吗?从SPAW计算到模型验证