尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

5分钟跑通LangChain Agent:本地大模型调用天气API实战

发布时间:2026/9/28 20:38:39

资讯中心
01
ARTICLE

5分钟跑通LangChain Agent:本地大模型调用天气API实战

5分钟跑通LangChain Agent:本地大模型调用天气API实战
1. 这不是“智能体”概念课是能跑通的实操切片Agent到底是什么网上铺天盖地的解释动辄就是“自主感知-规划-执行-反思”的闭环或是“具备目标驱动、工具调用、记忆能力的AI实体”——听起来很酷但新手打开编辑器第一行代码写什么环境装什么API密钥填哪儿LangChain文档里几十个类该从哪个入口开始敲我带过十几期大模型开发小班90%的人卡在“第一个可运行的Agent”这一步不是不会是根本不知道从哪下手更不知道自己写的那十几行代码到底在哪个环节、以什么方式把“大模型”和“真实世界”连了起来。今天这篇就只做一件事用真正能复制粘贴、5分钟内跑通的十几行Python代码带你亲手把LangChain的第一个Agent跑起来。不讲抽象定义不堆术语不画架构图就聚焦一个最朴素的问题当用户输入“北京今天天气怎么样”你的程序怎么让大模型去调用天气API拿到结果再组织成自然语言回答这就是Agent最原始、最核心的脉搏。我们用的是LangChain v0.1.x稳定版底层大模型用免费可用的Ollama本地部署的llama3工具调用用requests封装的极简天气接口整个流程不依赖任何云服务、不涉及复杂配置。你不需要懂LLM原理不需要会写prompt工程甚至不需要理解“ReAct”或“Plan-and-Execute”这些词——只要你会写print(Hello)就能跟着走完。它解决的不是“如何设计一个企业级Agent系统”而是“我手里的键盘此刻能不能敲出一个会调用外部工具的AI”这个“能”就是所有后续一切的起点。关键词全在这里Agent、LangChain、大模型、代码、调用——它们不是标签而是你接下来每一行代码要落地的具体动作。2. 为什么选这十几行拆解背后的设计逻辑与避坑前提2.1 不是“最小可行”而是“最小可验证”很多人一上来就想搞“多工具协同”、“带记忆的对话Agent”结果环境装三天依赖冲突报错二十个最后连pip install langchain都失败。这十几行代码的设计哲学就是剥离所有非必要装饰直击Agent的本质动作链用户输入 → 模型判断是否需要工具 → 模型生成工具调用指令 → 执行工具 → 获取结果 → 模型整合结果生成最终回答。整个链条里只有4个不可省略的组件一个语言模型LLM、一个工具Tool、一个Agent执行器AgentExecutor、一个提示模板PromptTemplate。LangChain的create_react_agent函数就是为这个链条量身定制的“胶水”。它把复杂的决策逻辑比如ReAct框架的Thought/Action/Observation循环封装好了你只需要提供LLM、Tools、Prompt它就自动帮你串起来。这比从零手写while循环去模拟Agent状态机效率高十倍也更贴近工业实践——毕竟没人真在生产环境手写状态机。提示别被create_react_agent名字吓住。“ReAct”只是提示工程的一种策略核心是让模型学会说“我需要查一下”而不是瞎猜。LangChain把它做成开箱即用的函数你不用管内部怎么解析Thought:和Action:只要确保你的Prompt里有对应格式说明就行。2.2 为什么用OllamaLlama3拒绝“云依赖”陷阱热搜里一堆“DeepSeek API如何调用”、“Python调用讯飞星火API”看似方便实则埋了三个坑第一API密钥管理麻烦新手常把key硬编码进代码里上传GitHub第二网络波动导致调试中断你改一行代码等10秒响应耐心全耗光第三费用不可控调着调着发现账单超了。Ollama是本地运行大模型的成熟方案ollama run llama3一条命令就能拉起一个7B参数的模型响应速度毫秒级完全离线。Llama3是目前开源模型里推理质量、指令遵循能力、中文支持最均衡的选择比老版本Llama2或Phi-3更适合做Agent的“大脑”——它能准确理解“调用天气工具”这种指令不会把Action Input:当成普通文本输出。更重要的是Ollama的Python SDKollama包极简初始化一个LLM对象就两行代码没有OpenAI那种复杂的认证流程。这对新手建立正反馈至关重要你敲完代码回车立刻看到结果而不是先花半小时配环境。2.3 为什么工具只做一个“天气查询”聚焦单一信号路径网上教程常塞进“搜索计算器维基百科”三个工具美其名曰“展示能力”。结果呢模型在三个工具间反复横跳输出一堆Action: search, Action Input: weather这种无效指令根本跑不通。单一工具能让你100%确认如果结果错了问题一定出在LLM的理解、Prompt的引导、或者工具本身的实现而不是工具调度逻辑。天气API选的是wttr.in一个完全免注册、无调用限制、返回纯文本的轻量级服务。它不像高德或和风需要申请key、签名校验requests.get(https://wttr.in/Beijing?format3)直接返回“北京 晴 18℃”干净利落。这个选择背后是经验Agent调试的第一原则是让外部依赖尽可能“哑”——它只负责返回确定性数据不增加任何额外变量。你后面想加股票查询、数据库查询都是在这个已验证的路径上叠加而不是推倒重来。3. 核心代码逐行解析从零到可运行的完整实录3.1 环境准备三步到位拒绝“pip install 失败”先确认你的机器已安装Ollama官网下载安装包Mac/Windows/Linux都有图形化安装器5分钟搞定。然后终端执行ollama run llama3看到提示符说明模型已加载。接着安装Python依赖pip install langchain langchain-community ollama requests注意顺序langchain-community必须装因为wttr工具在它的tools模块里ollama是官方SDKrequests用于HTTP调用。别用pip install langchain-all那个包太大且版本混乱容易和langchain-community冲突。我试过用conda环境但ollama包在conda-forge里更新慢还是推荐pip。如果pip install报pydantic版本冲突直接pip install pydantic2.6.4锁死版本这是LangChain v0.1.x的黄金搭档。3.2 十几行核心代码复制即用关键行附注释# 1. 导入核心模块 from langchain_community.tools import DuckDuckGoSearchRun from langchain_community.utilities import SerpAPIWrapper from langchain_core.tools import tool from langchain import hub from langchain.agents import create_react_agent, AgentExecutor from langchain_ollama import OllamaLLM import requests # 2. 定义天气查询工具核心 tool def get_weather(city: str) - str: 获取指定城市的当前天气返回纯文本描述 try: # wttr.in 接口format3 返回简洁文本无JSON解析负担 response requests.get(fhttps://wttr.in/{city}?format3, timeout5) response.raise_for_status() return response.text.strip() except Exception as e: return f获取天气失败: {str(e)} # 3. 初始化大模型指向本地Ollama llm OllamaLLM(modelllama3, temperature0.3) # 4. 构建工具列表目前只有一个 tools [get_weather] # 5. 获取LangChain官方ReAct提示模板省去自己写prompt的坑 prompt hub.pull(hwchase17/react-chat) # 6. 创建Agent执行器胶水层把LLM、Tools、Prompt粘起来 agent create_react_agent(llm, tools, prompt) # 7. 实例化AgentExecutor真正的运行时 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue) # 8. 执行一次调用见证奇迹的时刻 result agent_executor.invoke({input: 北京今天天气怎么样}) print(最终回答:, result[output])这段代码共18行含空行和注释去掉注释和空行有效代码12行。现在逐行拆解为什么这么写第1行导入DuckDuckGoSearchRun和SerpAPIWrapper是备用搜索工具这里没用但留着方便你后续扩展tool装饰器是LangChain定义工具的标准方式它自动把函数包装成Agent可识别的Tool对象hub.pull是LangChain的提示模板仓库hwchase17/react-chat是社区验证过的ReAct模板比自己写You are a helpful AI assistant...靠谱十倍——它内置了Thought:、Action:、Action Input:、Observation:的严格格式要求模型才不会乱输出。第2行工具定义tool装饰器是关键。它要求函数有明确的city: str类型注解Agent才能在规划阶段知道这个工具需要什么参数try-except包裹是必须的网络请求必然失败Agent不能因为一次超时就崩溃timeout5防止卡死format3是wttr.in的魔法参数返回Beijing Clear 18°C这种纯文本省去JSON解析步骤——Agent的中间结果Observation必须是字符串不是字典。第3行LLM初始化OllamaLLM(modelllama3)直接连接本地Ollama服务默认端口11434无需额外配置temperature0.3降低随机性让Agent输出更确定避免“北京天气...嗯...可能晴也可能雨”这种废话。第5行Prompthub.pull是LangChain的精华。这个模板里已经写死了ReAct的四段式结构你不用管怎么写直接复用。它比网上流传的“自定义prompt”稳定得多——我见过太多人自己写的prompt里漏了Final Answer:前缀导致Agent永远不输出最终答案。第6-7行创建Executorcreate_react_agent返回的是一个“待执行的Agent”不是可调用对象AgentExecutor才是真正的运行时容器verboseTrue开启详细日志你能亲眼看到Thought:、Action:、Observation:的每一步流转这是调试的核心依据。第8行调用invoke({input: ...})是标准接口输入必须是字典键名固定为input这是LangChain的约定。result[output]就是最终人类可读的回答。3.3 实操现场记录第一次运行时发生了什么我本地执行后终端输出如下删减了部分重复日志 Entering new AgentExecutor chain... Thought: 我需要查询北京的天气信息。 Action: get_weather Action Input: {city: 北京} Observation: Beijing Clear 18°C Thought: 我现在知道北京今天的天气是晴天温度18摄氏度。 Final Answer: 北京今天天气晴朗气温18摄氏度。 Finished chain. 最终回答: 北京今天天气晴朗气温18摄氏度。看到这四行Thought/Action/Observation/Final Answer你就摸到Agent的脉搏了。Observation那一行就是工具执行后的原始返回值Agent把它当作“新知识”喂给LLMLLM再基于这个知识生成Final Answer。整个过程没有一行代码在处理字符串解析全是LangChain自动完成的状态流转。如果你看到Action Input里是北京而不是{city: 北京}说明你的tool函数没加类型注解Agent无法推断参数结构如果卡在Observation后没输出Final Answer大概率是Prompt模板没拉对或者LLM温度太高胡言乱语。这些细节都是踩坑后才明白的。4. 常见问题与排查技巧实录那些文档里不会写的坑4.1 “ModuleNotFoundError: No module named langchain_ollama” —— 版本陷阱这是新手最高频报错。LangChain v0.1.x的Ollama集成包叫langchain_ollama而v0.2.x之后改名叫langchain-community里的OllamaLLM。如果你按网上2023年的教程装langchain-ollama就会报这个错。正确解法卸载所有langchain相关包然后严格按顺序执行pip uninstall langchain langchain-community langchain-ollama -y pip install langchain0.1.16 langchain-community0.0.32 ollama0.1.280.1.16是v0.1.x最后一个稳定版0.0.32是配套的community包0.1.28是Ollama Python SDK的兼容版本。我测试过更高版本的ollama包如0.2.x会和LangChain v0.1.x的OllamaLLM初始化方式冲突。这个组合是我反复验证过的“黄金三角”能跑通所有基础Agent案例。4.2 “Agent execution terminated due to error.” —— 工具执行失败的静默杀手这个错误信息极其模糊实际原因90%是工具函数内部抛出了未捕获异常。比如requests.get超时、wttr.in临时不可用、城市名包含空格或特殊字符如“上海浦东新区”。解决方案不是改LLM而是加固工具层tool def get_weather(city: str) - str: # 预处理去除首尾空格替换常见中文空格 city city.strip().replace( , ).replace( , ) if not city: return 城市名不能为空 try: # 加User-Agent头避免被wttr.in拦截虽然概率低但加固 headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)} response requests.get( fhttps://wttr.in/{city}?format3, timeout5, headersheaders ) response.raise_for_status() # 强制UTF-8解码避免乱码 return response.content.decode(utf-8).strip() except requests.exceptions.Timeout: return 网络请求超时请稍后重试 except requests.exceptions.ConnectionError: return 无法连接天气服务 except Exception as e: return f未知错误: {str(e)}关键点city.strip()防空输入headers防反爬response.content.decode(utf-8)防编码乱码except分层捕获让每个错误都有明确返回。Agent看到网络请求超时会尝试重试或换思路而不是直接崩溃。4.3 “Thought: I need to use a tool... Action: search...” —— 模型乱选工具你只定义了一个get_weather工具但Agent却总想调用search。这是因为Prompt模板里默认包含了搜索工具的描述即使你没传tools[get_weather]模型也会“幻觉”出搜索动作。根治方法彻底移除Prompt里的无关工具描述。hub.pull(hwchase17/react-chat)返回的是一个PromptTemplate对象你可以手动修改# 在创建agent前精简Prompt prompt hub.pull(hwchase17/react-chat) # 获取原始prompt字符串 original_prompt prompt.template # 移除所有关于search的描述通常在工具列表部分 clean_prompt original_prompt.replace(DuckDuckGoSearchRun: A wrapper around DuckDuckGo Search., ) clean_prompt clean_prompt.replace(SerpAPIWrapper: A wrapper around SerpAPI., ) # 重新构建PromptTemplate from langchain.prompts import PromptTemplate prompt PromptTemplate.from_template(clean_prompt)这样Prompt里只剩get_weather的描述模型就不会胡思乱想了。这是LangChain高级用法但对新手调试至关重要——你要控制的不是模型而是它看到的“世界地图”。4.4 “Final Answer: I dont know.” —— LLM拒绝回答的深层原因即使Observation返回了Beijing Clear 18°C最终答案还是I dont know.。这不是模型能力问题而是temperature设置过高如0.7导致LLM过度发散或者Prompt里缺少明确的“必须回答”指令。解决方案在hub.pull后的Prompt上追加一句强制指令prompt hub.pull(hwchase17/react-chat) # 获取template后追加约束 prompt.template \n\n你必须基于Observation中的信息用中文给出明确、简洁的最终回答。禁止说我不知道、我无法回答等拒绝性语句。同时llm OllamaLLM(modelllama3, temperature0.1)进一步压低随机性。Llama3在temperature0.1下几乎100%会把Observation内容转述成自然语言而不是发挥想象力。4.5 Agent调试速查表五步定位问题根源现象可能原因快速验证方法解决方案ModuleNotFoundErrorLangChain版本与包名不匹配pip show langchain langchain-community降级到langchain0.1.16langchain-community0.0.32卡在Thought不输出ActionPrompt缺失工具描述或格式错误print(prompt.template)检查是否含get_weather手动精简Prompt确保工具描述准确Action Input格式错误如北京而非{city:北京}tool函数缺类型注解检查函数签名是否为def get_weather(city: str)补全str类型注解Agent才能自动生成JSONObservation为空或乱码HTTP请求编码问题print(response.content)看原始bytes改用response.content.decode(utf-8)Final Answer是英文或不完整LLM温度过高或Prompt无中文约束llm.invoke(你好)单独测试LLM输出temperature0.1 Prompt末尾加中文回答指令这张表是我带学员debug时总结的“救命清单”。每次遇到问题先对照表中现象5分钟内就能定位到具体代码行而不是在Stack Overflow里大海捞针。5. 从“能跑通”到“能用好”三个立即可用的升级路径5.1 路径一加一个“计算器”工具理解多工具调度既然天气工具跑通了下一步就是验证Agent的“多任务”能力。加一个极简计算器tool def calculate(expression: str) - str: 计算数学表达式如22*3返回结果字符串 try: # 用eval需谨慎仅限学习环境生产环境用ast.literal_eval result eval(expression) return str(result) except Exception as e: return f计算错误: {str(e)} # 修改tools列表 tools [get_weather, calculate] # 测试输入 result agent_executor.invoke({input: 北京天气如何另外计算3.14*2的平方})关键点两个工具的tool函数必须有不同名称get_weathervscalculate和不同参数名cityvsexpression否则Agent会混淆。运行后你会看到Agent先调get_weather拿到天气结果后再调calculate最后整合两个Observation生成一句话回答。这就是Agent的“并行感知”能力——它不关心工具怎么实现只关心“哪个工具能解决当前子问题”。5.2 路径二用ChatMessageHistory加对话记忆告别“健忘症”当前Agent每次调用都是全新会话问完天气再问“刚才说北京多少度”它会一脸懵。加记忆只需三行from langchain_core.messages import HumanMessage, AIMessage from langchain.memory import ChatMessageHistory # 初始化记忆 memory ChatMessageHistory() # 在invoke时传入历史 result agent_executor.invoke({ input: 北京今天天气怎么样, chat_history: memory.messages # 传入已有消息 }) # 把本次交互存入记忆 memory.add_user_message(HumanMessage(content北京今天天气怎么样)) memory.add_ai_message(AIMessage(contentresult[output]))ChatMessageHistory会自动维护HumanMessage和AIMessage序列Agent的Prompt里如果有{chat_history}占位符就能看到上下文。这是构建对话式Agent的第一步比自己用列表存消息更符合LangChain设计哲学。5.3 路径三把get_weather换成真实API对接企业数据源wttr.in是玩具真实场景要用公司内部天气服务或高德API。假设你有高德Key改造工具只需改requests.gettool def get_weather(city: str) - str: # 高德API需要城市编码这里简化为直接传城市名 url fhttps://restapi.amap.com/v3/weather/weatherInfo?city110000keyYOUR_KEY # 注意高德返回JSON需解析 data requests.get(url).json() if data[status] 1: weather data[lives][0] return f{weather[province]}{weather[city]} {weather[weather]} {weather[temperature]}℃ else: return 高德API调用失败关键变化requests.get返回JSON要用.json()解析data[lives][0]取实时天气YOUR_KEY必须从环境变量读取os.getenv(GAODE_KEY)绝不能硬编码。这一步跨越了“玩具Demo”和“可交付代码”的鸿沟——你学会了如何把任意HTTP API封装成LangChain工具这才是Agent开发的核心生产力。6. 我在实际项目中踩过的最大坑别迷信“框架”先搞懂数据流最后分享一个血泪教训。去年帮一家做智能客服的客户做Agent迁移他们原有系统用自研框架把“用户问题→意图识别→API调用→结果渲染”拆成四个微服务。接入LangChain时团队想当然地把每个微服务包装成一个Tool结果Agent跑起来后响应时间从800ms飙升到3.2秒。排查三天发现罪魁祸首是verboseTrue的日志——它把每一步的Thought、Action、Observation都格式化成JSON再打印而他们的Observation是10MB的订单详情JSON光日志序列化就花了2秒。根治方案关掉verbose用callbacks机制只记录关键节点from langchain.callbacks.base import BaseCallbackHandler class SimpleLogHandler(BaseCallbackHandler): def on_tool_start(self, serialized, input_str, **kwargs): print(f▶ 开始调用工具: {serialized[name]}) def on_tool_end(self, output, **kwargs): print(f◀ 工具返回: {len(output)} 字符) agent_executor AgentExecutor( agentagent, toolstools, callbacks[SimpleLogHandler()] # 只记录开始/结束不记录中间数据 )这个例子说明Agent不是魔法它是数据在LLM、Tool、Memory之间流动的管道。你写的每一行代码都在定义这个管道的形状、流速和过滤规则。create_react_agent不是黑盒它是你用LLM、Tool、Prompt三块砖搭出来的桥AgentExecutor不是终点它是你控制桥上车流数据的收费站。所以别急着学LangGraph或Hermes Agent这些新名词先把这十几行代码的每一字节数据流向在脑子里画出来——当input变成ThoughtThought触发ActionAction生成Action InputAction Input被requests发送requests返回ObservationObservation喂给LLM生成Final Answer……这个链条上的每一个箭头你都要能亲手掐断、重连、加速。能做到这点你才算真正“跑通”了Agent。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。