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

100行Python代码,搭一个能干活的AI Agent

100行Python代码,搭一个能干活的AI Agent

原文首发于:点这里查看

跟大模型聊天人人都会,但你有没有想过——为什么ChatGPT能帮你订餐、查航班、写代码,而你调用API只会一问一答?
差别就两个字:Agent
大模型是大脑,但没手没脚没记忆。你问它"北京天气怎么样",它只会说"我无法访问实时数据"。Agent就是给大脑装上四肢、记忆和执行力——让它自己判断该用什么工具,执行完再思考下一步。
听起来很复杂?其实核心就一个公式:
Agent =LLM(大脑)+ Tools(双手)+ Memory(记忆)+ Loop(循环)
今天用100行Python代码,把这四个模块从零搭一遍。不依赖任何框架,跑完你就明白Agent到底是怎么回事。

00 环境准备

pipinstallopenai

用OpenAI SDK,兼容DeepSeek、智谱等国产API,改个base_url就行。这篇用DeepSeek做demo——便宜,而且支持按量付费。
你需要去https://platform.deepseek.com/注册拿一个API Key。

01 LLM调用 —— 给Agent装个大脑

第一块拼图:能跟大模型对话。

fromopenaiimportOpenAIfromdotenvimportload_dotenvimportos load_dotenv()client=OpenAI(# api_key="your-api-key", # 换成你的DeepSeek API Keyapi_key=os.getenv("DEEPSEEK_API_KEY"),# 或使用env方式存储apikeybase_url="https://api.deepseek.com")defask_llm(messages,tools=None):response=client.chat.completions.create(model="deepseek-v4-flash",messages=messages,tools=tools,tool_choice="auto",)returnresponse.choices[0].message res=ask_llm([{"role":"user","content":"你好"}])print(res)

这段代码本身没什么特别的,就是标准的API调用。但注意tools这个参数——这是Agent和普通聊天的核心分界线。
不传tools,模型只能聊天。传了tools,模型就知道"我还有这些工具可以用",在需要的时候会主动要求调用。tool_choice="auto"的意思是让模型自己判断:这个问题我直接答,还是得用工具?

⚠️ 踩坑提示 DeepSeek的deepseek-chat模型已废弃,对应deepseek-v4-flash模型中的非思考模式

02 工具定义 —— 给Agent装双手

工具就是普通的Python函数,外加一份给LLM看的"说明书"。

defcalculator(expression:str)->str:try:returnstr(eval(expression))except:return"计算错误"defget_weather(city:str)->str:mock={"北京":"晴 25℃","上海":"多云 28℃","深圳":"雷阵雨 30℃"}returnmock.get(city,f"暂无{city}天气数据")TOOLS=[{"type":"function","function":{"name":"calculator","description":"执行数学计算,输入数学表达式","parameters":{"type":"object","properties":{"expression":{"type":"string","description":"数学表达式,如 2+3*4"}},"required":["expression"]}}},{"type":"function","function":{"name":"get_weather","description":"查询指定城市的天气","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名称"}},"required":["city"]}}}]TOOL_MAP={"calculator":calculator,"get_weather":get_weather}

这里有个关键认知:LLM****不直接执行代码
它只做一件事——输出一段JSON,告诉你"我想调用calculator工具,参数是123 * 456 + 789"。真正执行计算的是你的代码。LLM的角色更像一个调度员,决定调用什么工具、传什么参数,但脏活累活都是你的程序干。
description字段很重要,写得越清晰,模型调用越准确。模型是靠读这个描述来理解工具用途的——你说"执行数学计算",它就知道算术题该找这个工具。

03 记忆 —— 让Agent记住上下文

classMemory:def__init__(self):self.messages=[]defadd(self,role,content,**kwargs):msg={"role":role,"content":content}msg.update(kwargs)self.messages.append(msg)defget_messages(self):returnself.messages.copy()

就这?就这么简单。
很多人觉得Agent的"记忆"很高深,其实本质就是维护一个messages列表。每次调用LLM时,把完整的对话历史传过去——LLM本身没有状态,所谓的"记住上下文"就是每轮都把历史消息全部塞进请求里。
这也解释了为什么聊天越长,API费用越高——因为每次请求都带着之前所有的对话。

04 Agent循环 —— 让Agent会思考

这是整个Agent的心脏。核心思路叫ReAct****模式:思考→行动→观察→重复,直到任务完成。

defrun_agent(user_input,max_steps=10):memory=Memory()memory.add("system","你是一个有用的助手,可以调用工具回答问题。")memory.add("user",user_input)forstepinrange(max_steps):print(f"\n--- 第{step+1}步 ---")response=ask_llm(memory.get_messages(),tools=TOOLS)ifnotresponse.tool_calls:print(f"Agent回答:{response.content}")returnresponse.content memory.add("assistant",response.contentor"",tool_calls=response.tool_calls)fortool_callinresponse.tool_calls:name=tool_call.function.name args=json.loads(tool_call.function.arguments)print(f"调用工具:{name}({args})")result=TOOL_MAP[name](**args)print(f"工具返回:{result}")memory.add("tool",result,tool_call_id=tool_call.id)return"达到最大步数,Agent停止"

拆解这个循环:

  1. 思考:把对话历史和工具列表发给LLM,LLM决定下一步干什么
  2. 判断:如果LLM没有请求调用工具,说明它觉得可以直接回答了,循环结束
  3. 行动:LLM说"我要查北京天气",你的代码就执行get_weather("北京")
  4. 观察:把工具执行结果塞回messages,让LLM看到结果
  5. 重复:LLM拿到结果后再思考,可能还需要调别的工具,也可能可以直接回答了
    max_steps是安全阀,防止Agent陷入死循环。实际使用中10步足够处理大部分任务。

跑起来看效果

# 测试1:简单计算run_agent("帮我算一下 123 * 456 + 789")

输出:

两步完成:第一步调计算器,第二步直接回答。

# 测试2:多步骤任务run_agent("北京和上海哪个温度高?并帮我算一下高多少?")

输出:

Silas说
写完这100行代码,最大的感受是:Agent一点都不神秘
网上铺天盖地的Agent框架——LangChain、AutoGen、CrewAI——把这件事包装得很复杂。但你把核心扒开看,就是一个while循环:LLM决定调什么工具,你的代码执行,结果传回去,循环直到完成。框架做的事,无非是帮你把这个循环封装好,再加上一些工程化的东西(重试、超时、日志)。
我的建议:先手写一遍,再用框架
不是框架不好,是你不理解原理直接用框架,出了问题完全不知道怎么排查。你不知道tool_calls的格式长什么样,不知道messages里每条消息的role有什么讲究,调试的时候就是两眼一抹黑。
还有一点:别急着给Agent加复杂的Planning和Multi-Agent协作。先把这个最小闭环跑通,加一个你自己业务场景需要的工具(比如查数据库、调内部API),让它真正干一件有用的事。能稳定跑一周,再考虑扩展。
Agent的价值不在于架构多精巧,在于它能不能稳定地把一件事干好。


跑通代码后,可以试试这些扩展方向:

  1. 换个工具:把get_weather换成查数据库、调内部API、发邮件——只要是个Python函数就能当工具
  2. 加RAG:给Agent接一个知识库,让它能查文档回答问题
  3. 多Agent协作:多个Agent分工合作,比如一个负责搜索、一个负责写作
  4. 试试框架:理解原理后再用LangChain或CrewAI,你会发现它们其实就是帮你封装了这套循环
    完整代码我已经整理好了,复制就能跑。你给Agent加了什么有意思的工具?评论区聊聊。
    觉得有用的话,转给也在折腾AI的朋友。
    关注我,持续分享AI实操和踩坑记录。

""" 最小AI Agent实现 —— 100行代码搞定 Agent = LLM + Tools + Memory + Loop """fromopenaiimportOpenAIimportjsonfromdotenvimportload_dotenvimportos load_dotenv()# ============ 1. LLM调用(大脑)============client=OpenAI(# api_key="your-api-key", # 换成你的DeepSeek API Keyapi_key=os.getenv("DEEPSEEK_API_KEY"),# 或使用env方式存储apikeybase_url="https://api.deepseek.com")defask_llm(messages,tools=None):response=client.chat.completions.create(model="deepseek-v4-flash",messages=messages,tools=tools,tool_choice="auto",)returnresponse.choices[0].message# ============ 2. 工具定义(双手)============defcalculator(expression:str)->str:try:returnstr(eval(expression))except:return"计算错误"defget_weather(city:str)->str:mock={"北京":"晴 25℃","上海":"多云 28℃","深圳":"雷阵雨 30℃"}returnmock.get(city,f"暂无{city}天气数据")TOOLS=[{"type":"function","function":{"name":"calculator","description":"执行数学计算,输入数学表达式","parameters":{"type":"object","properties":{"expression":{"type":"string","description":"数学表达式,如 2+3*4"}},"required":["expression"]}}},{"type":"function","function":{"name":"get_weather","description":"查询指定城市的天气","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名称"}},"required":["city"]}}}]TOOL_MAP={"calculator":calculator,"get_weather":get_weather}# ============ 3. 记忆(对话历史)============classMemory:def__init__(self):self.messages=[]defadd(self,role,content,**kwargs):msg={"role":role,"content":content}msg.update(kwargs)self.messages.append(msg)defget_messages(self):returnself.messages.copy()# ============ 4. Agent循环(心脏)============defrun_agent(user_input,max_steps=10):memory=Memory()memory.add("system","你是一个有用的助手,可以调用工具回答问题。")memory.add("user",user_input)forstepinrange(max_steps):print(f"\n--- 第{step+1}步 ---")response=ask_llm(memory.get_messages(),tools=TOOLS)ifnotresponse.tool_calls:print(f"Agent回答:{response.content}")returnresponse.content memory.add("assistant",response.contentor"",tool_calls=response.tool_calls)fortool_callinresponse.tool_calls:name=tool_call.function.name args=json.loads(tool_call.function.arguments)print(f"调用工具:{name}({args})")result=TOOL_MAP[name](**args)print(f"工具返回:{result}")memory.add("tool",result,tool_call_id=tool_call.id)return"达到最大步数,Agent停止"# ============ 5. 测试 ============if__name__=="__main__":run_agent("北京和上海哪个温度高?并帮我算一下高多少?")

THE END

RAG知识库搭建大揭秘:原来这么简单,还能这么有趣!
大模型到底怎么思考?一篇看懂 Prompt、思维链、思维树
Python数据分析入门:从零开始玩转数据
简明教程:实现OpenCLaw轻量级应用服务器部署及Ollama大模型本地化
Dify+Ollama模型搭建攻略:本地环境实战指南


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

相关文章:

  • 2026指南:南京长途搬家服务品牌实力解析与跨城优选方案 - 卓企推荐
  • 基于ReAct与Function Calling构建本地AI编程助手:从原理到实战
  • Meta开源多模态AI模型Muse Glimmer与Spark 1.2:从权重下载到本地部署实战指南
  • 贪心算法解决区间覆盖问题:从LeetCode 1024视频拼接到通用模板
  • 碧蓝航线Alas自动化脚本从零开始避坑指南:无缝委托科研与全自动大世界实战
  • 无血清培养基为什么越来越常用?从批间差异、动物源风险到下游纯化
  • 【已开源】手写模拟器-文本/docx 一键变逼真手写图片,告别手抄
  • Python多线程下载实战:从并发原理到小说爬虫优化
  • 达梦数据库dm.ini参数深度解析:从核心原理到生产调优实战
  • SSH免密登录实战:PEM密钥原理、配置与安全实践
  • SteamCMD命令行工具:精准下载与管理Steam创意工坊MOD文件
  • AI辅助学术写作全流程工具链与效率提升实践
  • LangChain RAG实战:从文档加载到检索增强生成的完整指南
  • DeepSeek V4 Pro 高峰输出涨至 27 元:一个老系统维护者的零成本提效实践
  • 从黑盒子到可控开关:MOS管核心原理、参数选型与实战电路设计
  • 【学习地图】Linux学习类 · 文章索引
  • 栖霞市靠谱的本地正规防水补漏维修团队哪家好_复漏整治口碑资质实力全面对比推荐 - 雨婺虹修缮
  • 礼子期深度解读商标注册全流程,带你看懂从查重检索到成功拿证,整个周期需要历经哪些关键关卡
  • A4982与TMC2209步进驱动对比:从噪音、精度到OPENPNP配置实战
  • RGB888与RGB565颜色转换原理、对照表生成与嵌入式视觉优化实践
  • 2026土工材料防水材料生产厂实力测评,零套路不踩坑优选攻略 - mypinpai
  • 文档化流程审查:核心逻辑与实操技巧
  • 基于AI与规则引擎的邮件自动化处理:从NLP解析到任务执行
  • 安顺本地装修公司性价比分析:核心维度全解析 - 装企精灵GEO
  • TMC2209串口通信全解析:从硬件连接到软件配置,解锁静音与堵转检测
  • NVIDIA Profile Inspector 教程:解锁驱动隐藏设置,为每款游戏定制专属性能方案
  • 宜宾老胡装饰深度解析:宜宾装修公司该如何理性挑选 - 收录优先
  • 基于LP3667B的5V1A反激开关电源设计全解析:从原理到PCB布局
  • 高校AI竞赛实战指南:从PyTorch到项目部署的完整闭环
  • DeepSeek-V4-Pro-0813 API 更新:官方参数、价格、Codex 接入与成本计算