尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

从零构建AI Agent:基于LangChain的智能天气助手开发实战

从零构建AI Agent:基于LangChain的智能天气助手开发实战 1. 项目概述从概念到实践的跨越最近和不少同行交流发现大家对于“AI Agent”这个概念既兴奋又困惑。兴奋的是这似乎是继大语言模型之后又一个能真正落地的AI范式困惑的是网上资料要么过于学术化讲一堆“智能体”、“强化学习”、“马尔可夫决策过程”要么就是某个大厂发布的、离我们实际开发很远的框架宣传。这让我想起几年前刚开始接触微服务架构时的状态——概念满天飞但第一个“Hello World”服务到底该怎么搭反而找不到一个接地气的指南。所以我想抛开那些宏大的叙事就围绕“构建你的第一个AI Agent”这个目标用一篇长文把从核心认知到一行行代码落地的全过程拆解清楚。这个“第一个”Agent我们不追求多复杂的功能而是要让它具备最核心的特质能理解目标能调用工具比如搜索信息、执行计算并能根据结果自主决策下一步动作。完成它你就能建立起对AI Agent开发最直观的肌肉记忆。这篇文章适合谁呢如果你是一名有一定Python基础的开发者对LLM API调用有过初步尝试比如用过OpenAI或国内大模型的接口现在想迈出从“单次问答”到“自动执行任务”的关键一步那么这里就是为你准备的。我们将使用目前生态最成熟、最适合入门的LangChain框架结合一个“联网查询天气并给出穿衣建议”的经典场景手把手完成构建。你会发现一个具备自主性的AI Agent其内核可能比你想象的要清晰和简洁。2. AI Agent核心架构深度拆解在动手写代码之前我们必须先统一思想理解AI Agent究竟为何物。很多人把它简单理解为一个“高级的ChatGPT”这是最大的误区。核心区别在于“自主性”和“闭环”。2.1 核心组件大脑、工具与记忆一个典型的AI Agent由三个核心部分组成我们可以用一个专业的旅行顾问来类比推理核心大脑 - LLM这是Agent的决策中心通常由一个大语言模型担任。它的职责不是直接给出最终答案而是规划、决策和反思。就像旅行顾问他的价值不是背诵旅游手册而是根据你的需求“我想放松预算有限喜欢美食”规划出“先去A地参观中午在B餐厅用餐下午去C景点”这样的方案。在Agent中LLM负责解析用户目标决定调用哪个工具并解读工具返回的结果。工具集双手 - ToolsLLM本身是“闭门造车”的它的知识有截止日期也无法直接操作外部世界。工具就是它为Agent赋予的“双手”。例如SearchTool让Agent能获取实时信息。CalculatorTool让Agent能进行精确计算。APITool让Agent能操作其他软件系统如发送邮件、修改数据库。 在我们的天气Agent里就会给Agent提供一个GetWeatherTool让它能查询实时天气。记忆体经验 - Memory这是Agent实现多轮对话和持续学习的关键。它分为两种短期记忆ConversationBufferMemory保存当前对话的上下文让Agent记得你刚才说了什么。长期记忆VectorStore可以将历史对话中的重要信息如用户的偏好“我对花粉过敏”存储到向量数据库中供未来会话参考实现个性化。2.2 工作流思考、行动、观察的循环Agent的核心工作流是一个经典的ReAct (Reason Act)循环这也是其“自主性”的体现思考ThinkLLM根据用户输入和当前记忆分析目标。例如用户说“北京明天适合穿什么”LLM会推理出“要回答穿衣建议我需要知道明天的天气。我需要调用天气查询工具。”行动ActLLM决定具体的行动指令例如生成一个结构化的调用工具名GetWeatherTool 输入参数{city: 北京, date: 明天}。观察Observe工具执行完毕将结果如“北京明天晴5~15°C北风3级”返回给LLM。再思考与输出LLM观察到工具返回的结果结合最初的问题进行最终推理生成面向用户的回答“北京明天天气晴朗气温5-15度早晚温差较大。建议内搭衬衫或薄毛衣外穿风衣或夹克。”这个“思考-行动-观察”的循环可能会进行多次。例如用户问“帮我对比一下北京和上海本周末的天气并推荐一个更适合出游的城市”。Agent可能需要先调用两次天气工具再调用一次计算工具来综合评分最后进行推理总结。注意这里容易混淆的是“工具调用”和“函数调用”。函数调用是LLM本身提供的一种能力让模型能输出结构化参数。而Agent框架中的“工具调用”是一个更上层的概念它利用LLM的函数调用能力但将其纳入一个可管理、可扩展的循环框架中。你可以简单理解为函数调用是“技能”而Agent框架是管理和运用这些技能的“工作流引擎”。3. 开发环境与工具链搭建工欲善其事必先利其器。构建AI Agent虽然核心逻辑不复杂但一个稳定、高效的开发环境能避免很多后期麻烦。3.1 基础环境配置首先强烈建议使用Python 3.10或以上版本这是大多数AI框架稳定支持的分水岭。管理Python环境我首推conda或uv。conda生态更成熟uv是新兴的、速度极快的包管理器和安装器。这里以conda为例# 创建并激活一个名为ai_agent的独立环境 conda create -n ai_agent python3.10 conda activate ai_agent使用独立环境可以避免项目间的包版本冲突这是血泪教训。曾经因为一个底层依赖的变动导致整个Agent调度逻辑出错排查了大半天。3.2 核心框架与库选型接下来是安装核心库。LangChain是我们的主框架它提供了构建Agent所需的所有抽象和组件。pip install langchain langchain-communityLangChain是一个庞大的生态langchain是核心langchain-community则包含了大量第三方集成的工具和组件。为什么选LangChain因为它目前拥有最丰富的工具集成、最清晰的抽象层次和最活跃的社区。对于初学者跟着最大的生态走踩坑时更容易找到解决方案。然后我们需要一个LLM来充当Agent的“大脑”。这里有两个主流选择OpenAI API最稳定对Agent各种模式支持最好但需要网络环境和API Key。Ollama 本地模型完全本地运行隐私性好成本低但需要本地计算资源且小模型的推理和规划能力可能较弱。为了第一次构建的体验顺畅我们选择OpenAI GPT-3.5-turbo作为起点。安装OpenAI的SDKpip install openai同时我们需要安装langchain-openai这个官方集成包它提供了更便捷的LangChain调用方式。pip install langchain-openai3.3 辅助工具与密钥管理我们的天气Agent需要一个查询天气的工具。我们可以模拟一个但为了更真实这里使用一个免费的公开天气API比如requests库来调用。同时为了解析API返回的JSON数据Python标准库就足够了。pip install requests最后也是最重要的一步安全管理你的API密钥。绝对不要将密钥硬编码在代码中或上传到GitHub。推荐的方式是使用环境变量。# 在终端中设置临时 export OPENAI_API_KEY你的-sk-xxx密钥 # 或者更推荐使用python-dotenv管理 pip install python-dotenv然后在项目根目录创建一个.env文件内容如下OPENAI_API_KEY你的-sk-xxx密钥 WEATHER_API_KEY你的天气API密钥如果用真实API在代码开头通过dotenv加载这些变量。这样你的密钥就安全了代码也可以放心分享。4. 实战构建“智能天气穿衣助手”Agent现在让我们开始构建第一个Agent。我们将创建一个能理解用户关于天气和穿衣的查询自动调用天气工具获取数据并给出个性化建议的智能体。4.1 第一步定义核心工具Tool工具是Agent与外界交互的桥梁。我们先定义一个获取天气的工具。由于稳定的免费天气API较少且可能有调用限制我们先定义一个模拟工具其核心是掌握定义工具的格式。# weather_tool.py from langchain.tools import tool import requests import os from dotenv import load_dotenv load_dotenv() # 加载.env文件中的环境变量 tool def get_weather(city: str, date: str 今天) - str: 根据城市和日期获取天气预报信息。 Args: city: 城市名称例如“北京”、“上海”。 date: 日期支持“今天”、“明天”、“后天”或具体的日期字符串。 Returns: 返回该城市指定日期的天气情况描述字符串。 # 这里是模拟实现。在实际应用中你应该替换为一个真实的天气API调用。 # 例如使用和风天气、OpenWeatherMap等。 # real_api_key os.getenv(WEATHER_API_KEY) # url fhttps://api.weatherapi.com/v1/forecast.json?key{real_api_key}q{city}days3 # response requests.get(url).json() # ... 解析response提取对应date的天气 ... # 模拟返回数据 weather_data { 北京: {今天: 晴 5~15°C 北风3级, 明天: 多云转晴 8~18°C 微风, 后天: 阴 3~12°C 东风2级}, 上海: {今天: 小雨 10~18°C 东南风4级, 明天: 阴 12~20°C 微风, 后天: 晴 15~22°C 西风3级}, 广州: {今天: 雷阵雨 24~30°C 南风5级, 明天: 大雨 23~28°C 南风6级, 后天: 多云 24~31°C 微风}, } city_data weather_data.get(city, {}) if not city_data: return f抱歉未找到{city}的天气信息。 # 简单的日期映射逻辑 date_map {今天: 0, 明天: 1, 后天: 2} date_key date if date in city_data else (list(city_data.keys())[date_map.get(date, 0)] if date in date_map else date) forecast city_data.get(date_key, 暂无该日期预报) return f{city}{date}的天气是{forecast}关键点解析tool装饰器这是LangChain将普通Python函数转化为Agent可识别工具的关键。它自动为函数生成描述LLM会阅读这个描述来决定何时调用它。类型提示Type Hintscity: str和- str非常重要。它们帮助LangChain为LLM生成更准确的函数调用规格大幅提升工具调用的准确率。文档字符串Docstring函数下的三引号描述是给LLM看的“工具说明书”。务必清晰、准确地说明工具的用途、参数和返回值。这是Agent能否正确使用工具的决定性因素。4.2 第二步初始化Agent的大脑LLM与记忆有了工具我们需要初始化LLM和记忆模块。# agent_core.py from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder import os from dotenv import load_dotenv load_dotenv() # 1. 初始化LLM # 使用gpt-3.5-turbo-1106或gpt-4-turbo它们对工具调用支持更好 llm ChatOpenAI( modelgpt-3.5-turbo-1106, temperature0, # 对于执行任务的Agenttemperature建议设为0或接近0保证输出的稳定性 openai_api_keyos.getenv(OPENAI_API_KEY) ) # 2. 初始化记忆 # ConversationBufferMemory会保存对话历史并自动提供给LLM作为上下文 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 3. 构建提示词模板Prompt Template # 这是指导Agent行为的“宪法”至关重要。 prompt ChatPromptTemplate.from_messages([ (system, 你是一个专业的天气生活助手。你的职责是 1. 根据用户的问题判断是否需要查询天气。 2. 如果需要你必须使用get_weather工具获取准确的天气信息。 3. 结合天气信息为用户提供穿衣、出行等方面的实用建议。 4. 如果用户的问题与天气无关请礼貌地告知你的能力范围。 请始终遵循思考-行动-观察的步骤。先思考用户需要什么信息再调用工具最后给出整合后的建议。), MessagesPlaceholder(variable_namechat_history), # 这里会自动插入历史对话 (human, {input}), # 这里是用户的当前输入 MessagesPlaceholder(variable_nameagent_scratchpad), # 这里是Agent思考和执行工具调用的暂存区由框架自动填充 ])实操心得System Prompt设计这是Agent的“人格”和“行为准则”。写得越具体Agent的表现就越可控。明确告诉它“必须使用工具”能有效减少它胡编乱造天气数据的情况LLM的幻觉问题。Temperature参数对于任务型Agent通常设置为0或0.1以追求最大程度的确定性和可重复性。如果你希望Agent有一些创意性的回答比如生成诗意的天气描述可以适当调高。MemoryConversationBufferMemory简单易用但所有历史对话都会无差别地送入LLM上下文可能导致token消耗过快。对于长对话可以考虑ConversationSummaryMemory或ConversationBufferWindowMemory只保留最近N轮。4.3 第三步组装并运行你的第一个Agent现在把工具、LLM、记忆和提示词模板组装起来形成可执行的Agent。# main.py from weather_tool import get_weather from agent_core import llm, memory, prompt # 1. 准备工具列表 tools [get_weather] # 2. 创建Agent # create_openai_tools_agent是LangChain提供的一个高级封装专门用于OpenAI模型工具的场景 agent create_openai_tools_agent(llm, tools, prompt) # 3. 创建Agent执行器Executor # 这是真正驱动循环的部分它绑定了Agent、工具和记忆。 agent_executor AgentExecutor( agentagent, toolstools, memorymemory, verboseTrue, # 强烈建议在调试时开启可以看到Agent内部的“思考过程” handle_parsing_errorsTrue, # 处理LLM输出解析错误避免程序崩溃 max_iterations5, # 限制ReAct循环的最大次数防止死循环 ) # 4. 运行Agent print(天气助手Agent已启动输入退出或quit结束对话。) while True: try: user_input input(\n你) if user_input.lower() in [退出, quit, exit]: print(助手再见) break # 调用执行器 response agent_executor.invoke({input: user_input}) print(f助手{response[output]}) except Exception as e: print(f出错了{e})运行python main.py你会看到类似以下的交互过程verboseTrue时你北京明天天气怎么样 进入新的Agent执行链... 思考用户想知道北京明天的天气。我需要使用get_weather工具来获取信息。 行动调用get_weather工具参数{city: 北京, date: 明天} 观察北京明天的天气是多云转晴 8~18°C 微风 思考我已经获取了天气信息现在可以直接回答用户。 助手北京明天天气是多云转晴气温在8到18摄氏度之间风力不大是微风。这就是你的第一个AI Agent在工作它自动完成了“思考-调用工具-观察-回答”的完整循环。4.4 第四步进阶功能——让Agent更“智能”基础的Agent已经跑通但我们可以让它更强大、更实用。4.4.1 增加多个工具一个真正的助手不会只查天气。我们可以轻松添加更多工具。# more_tools.py from langchain.tools import tool from datetime import datetime tool def get_current_time(timezone: str Asia/Shanghai) - str: 获取指定时区的当前时间。 # 这里简化处理实际应用可使用pytz库 now datetime.now() return f当前时间{timezone}是{now.strftime(%Y-%m-%d %H:%M:%S)} tool def clothing_suggestion(temperature: int, weather_condition: str) - str: 根据温度和天气状况提供穿衣建议。 suggestions [] if temperature 10: suggestions.append(建议穿着厚外套、毛衣、围巾注意保暖。) elif temperature 20: suggestions.append(建议穿着夹克、卫衣、长袖T恤等。) else: suggestions.append(可以穿着短袖、衬衫等轻薄衣物。) if 雨 in weather_condition: suggestions.append(今天有雨请务必携带雨具。) if 风 in weather_condition and 大 in weather_condition: suggestions.append(风较大建议固定好衣物注意防风。) return .join(suggestions) if suggestions else 根据当前天气穿着舒适即可。然后在main.py中将新工具加入列表tools [get_weather, get_current_time, clothing_suggestion]。现在Agent就能回答“现在几点”和“15度下雨天穿什么”这类复合问题了。4.4.2 使用更强大的Agent类型create_openai_tools_agent是一种类型。LangChain还提供了其他预设的Agent类型适用于不同场景ZERO_SHOT_REACT_DESCRIPTION最通用适用于工具描述清晰的情况。OPENAI_FUNCTIONS专为OpenAI函数调用优化我们上面用的类似这种。STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION适合工具参数非常复杂的场景。你可以通过from langchain.agents import initialize_agent来尝试不同的Agent类型观察其行为差异。4.4.3 连接真实数据源将模拟的get_weather工具替换为真实的API调用。以和风天气为例需注册获取API Keyimport requests import os tool def get_weather_real(city: str, date: str 今天) - str: 使用和风天气API获取实时天气预报。 api_key os.getenv(HF_WEATHER_KEY) # 1. 先通过城市搜索API获取location_id search_url fhttps://geoapi.qweather.com/v2/city/lookup?key{api_key}location{city} loc_resp requests.get(search_url).json() if loc_resp[code] ! 200: return f城市{city}查询失败。 location_id loc_resp[location][0][id] # 2. 获取3天预报 forecast_url fhttps://devapi.qweather.com/v7/weather/3d?key{api_key}location{location_id} forecast_resp requests.get(forecast_url).json() # 3. 解析对应日期的数据简化逻辑 date_index {今天:0, 明天:1, 后天:2}.get(date, 0) day_forecast forecast_resp[daily][date_index] result f{city}{date}白天{day_forecast[textDay]}夜间{day_forecast[textNight]}气温{day_forecast[tempMin]}~{day_forecast[tempMax]}°C。 return result重要提示调用真实API时务必做好错误处理网络超时、API限额、返回数据格式异常并考虑加入请求重试机制这是生产级应用稳定性的基础。5. 常见问题、调试技巧与优化实录构建和运行Agent的过程中你一定会遇到各种问题。下面是我踩过的一些坑和总结的排查经验。5.1 Agent不调用工具直接胡编乱造答案现象你问“北京天气”它直接回答“北京今天天气很好阳光明媚...”而不是去调用工具。原因与解决System Prompt指令不明确在Prompt中没有强制要求它必须使用工具。解决在System Prompt中加入强硬指令如“你必须使用可用的工具来获取信息严禁凭空猜测。”工具描述不清工具的docstring写得太模糊LLM无法理解这个工具是干嘛的或者何时该用它。解决重写工具描述使用清晰、无歧义的语言并举例说明输入输出例如“当用户询问任何关于未来或当前天气情况的问题时使用此工具。”LLM能力不足如果使用较小的本地模型其工具调用和遵循指令的能力可能较弱。解决换用能力更强的模型如GPT-4系列或在Prompt中提供更详细的示例Few-Shot Prompting。5.2 工具调用参数错误或格式不对现象Agent尝试调用工具但日志显示参数错误例如把城市名city传成了数字。原因与解决LLM误解了用户意图用户说“帮我看看帝都明天咋样”LLM可能无法将“帝都”映射到city: “北京”。解决可以在工具调用前加一层处理或者在Prompt中明确“请将口语化的城市名转换为标准的官方名称”。函数签名定义不清晰确保工具函数的参数有明确的类型提示str,int等和清晰的参数名。LangChain依赖这些信息为LLM生成准确的调用规范。开启Verbose模式这是最重要的调试手段。设置AgentExecutor(verboseTrue)你能看到LLM完整的“思考”链和传递给工具的原始参数精准定位问题所在。5.3 陷入死循环或迭代次数过多现象Agent不停地调用工具就是不输出最终答案直到达到max_iterations限制。原因与解决工具返回的结果无法满足LLM做出最终决策例如工具返回的天气信息格式混乱LLM看不懂于是它想再调用一次工具或调用其他工具来“厘清”信息。解决优化工具返回值的格式确保是清晰、结构化的文本。LLM喜欢干净的数据。任务过于复杂超出了预设的迭代步数比如用户问“规划一个北京上海广州三地一周的出差行程考虑天气和交通”。解决合理设置max_iterations比如10-15或者设计更宏观的“子任务规划工具”让Agent先分解任务再逐一解决。在Prompt中明确结束条件在System Prompt里告诉Agent“当你获得了足够的信息来回答用户的问题时请直接给出最终答案停止调用工具。”5.4 性能与成本优化当你的Agent开始处理复杂任务或频繁调用时就需要考虑优化。Token消耗与上下文管理问题ConversationBufferMemory会积累所有历史导致每次请求的token数越来越多成本激增速度变慢。解决使用ConversationSummaryMemory让LLM定期总结长对话只保留总结摘要。使用ConversationBufferWindowMemory(k5)只保留最近5轮对话。在非必要时主动清空记忆memory.clear()。工具调用的延迟问题如果工具需要调用慢速API如某些需要数秒响应的数据库查询会拖慢整个Agent的响应。解决异步调用如果框架和工具支持使用异步async/await来并发执行多个工具调用。设置超时为工具调用设置合理的超时时间避免一个慢工具卡死整个Agent。缓存对于结果不常变的数据如城市信息在工具层添加缓存机制。选择性价比更高的LLM对于逻辑简单、工具调用明确的任务可以尝试使用更便宜、更快的模型如gpt-3.5-turbo-instruct补全模型或 Claude Haiku。将复杂的规划任务由强模型如GPT-4执行和简单的执行任务由弱模型或规则引擎执行分离形成多智能体协作的架构。5.5 一个实用的调试检查清单当你遇到问题时可以按以下顺序排查问题现象可能原因检查点Agent完全不调用工具1. Prompt指令不明确2. 工具描述太差3. LLM能力不足1. 检查System Prompt加入强制使用工具的语句。2. 打印tools列表确认工具已正确加载且描述清晰。3. 开启verboseTrue看LLM的“思考”步骤是否提到了工具。工具调用参数错误1. LLM理解偏差2. 函数签名问题1. 在verbose日志中查看LLM生成的原始调用参数。2. 检查工具函数的参数名和类型提示是否准确。Agent输出混乱或无关内容1. Temperature值过高2. 上下文混乱1. 将temperature降至0或0.1。2. 检查记忆内容看是否混入了无关对话历史。尝试清空记忆。响应速度极慢1. 网络或API延迟2. 上下文过长1. 为工具调用和LLM调用添加超时和重试。2. 切换记忆模式为窗口记忆或摘要记忆减少token数。构建第一个AI Agent的过程就像教一个聪明的实习生如何工作。你需要清晰地定义它的职责System Prompt为它准备好所有可能用到的资源和手册Tools并建立一套标准的工作流程ReAct循环。一开始它可能会犯错调用错工具或者理解偏差但通过清晰的指令、良好的工具设计和细致的调试它会变得越来越可靠。从这个简单的天气助手出发你已经掌握了AI Agent最核心的构建逻辑。接下来你可以尝试为它接入数据库、知识库RAG、甚至赋予它自动化执行脚本的能力去解决更实际、更复杂的问题。
返回列表