多工具协同Agent实战:用LangChain构建越南市场情报系统 【导航台账】老蒋的技术博客全系列文章汇总持续更新从单工具到多工具协同一个20年IT老兵的Agent进阶之路本文是《从RAG到Agent20年IT老兵的AI智能体实战笔记》专栏第3篇上一篇《我的第一个工具调用Agent从零构建“知识库计算器时间文件”四合一智能体》专栏简介20年IT老兵从RAG到Agent系统进阶。聚焦制造业智能问答客服、数据质量巡检、数仓分层设计、知识库检索增强、设备智能化等场景分享可复用的工程化代码与实践心得。一、引言从“单工具”到“多工具协同”的能力跃迁在C1《我的第一个工具调用Agent》中我们实现了一个能调用计算器、时间查询、文件读写、知识库检索四项能力的Agent让AI第一次“动了起来”。但现实世界的业务问题远比“现在几点了”复杂得多。以制造业数据管理场景为例“帮我查一下胡志明市所有设备的在线率结合近期汇率波动生成一份市场运营简报”——这涉及设备数据查询、汇率分析、市场情报检索、报告生成四个步骤如果Agent只能调用单个工具这个问题就无法解决我们需要的是Agent能自主拆解复杂任务按正确顺序调用多个工具并将中间结果传递下去C2的核心目标就是构建一个具备多工具协同能力的Agent让它能像人类一样完成“感知→分析→报告”的完整工作流。本文基于“智联工坊”虚拟智能工厂的越南市场场景完整记录了一个多工具协同Agent从设计到实现的全过程。二、场景还原智联工坊的“越南之困”2.1 智联工坊是谁智联工坊是虚拟的智能工厂是一家50人规模的物联网科技公司产品涵盖商用智能交互屏、智能环境监测终端、资产追踪定位器等。其商用智能交互屏纸巾机曾在国内铺货5万台并成功出海越南市场。2.2 越南市场的真实痛点智联工坊的商用智能交互屏曾经进入越南市场在胡志明市、河内、岘港三城部署了近1500台设备。团队很快遇到了几个棘手问题痛点具体表现设备运营盲区设备在线率、扫码成功率无法实时感知故障全靠客户电话投诉汇率波动影响越南盾兑人民币汇率波动剧烈直接影响设备成本和利润但缺乏自动监控竞品信息滞后越南本地竞品动态、支付政策变化无法及时获取决策全靠人肉搜索报告生成低效每周需要人工汇总数据撰写市场简报耗时2-3小时核心问题如果有一个AI Agent能自动完成“设备监控→汇率分析→情报检索→报告生成”的闭环团队就能从繁琐的手工工作中解放出来。这正是C2要解决的问题。三、技术方案四大工具链的设计与实现C2的Agent架构遵循“感知→分析→报告”三层逻辑由四个工具协同完成用户提问 ↓ 【感知层】MQTT设备状态模拟器 → 获取1500台设备运营数据 ↓ 【分析层】汇率查询器 市场情报检索器 → 获取外部环境数据 ↓ 【报告层】多语言报告生成器 → 生成结构化情报报告 ↓ 返回结果工具1MQTT设备状态模拟器tools/mqtt_simulator.pytool def fetch_vietnam_device_status(city: str None) - str: 功能描述获取越南地区设备的运营状态数据。 设计思路 1. 模拟越南三城胡志明市、河内、岘港共1500台设备的数据上报 2. 每城500台在线率88%贴近真实IoT场景 3. 返回设备总数、在线率、平均扫码成功率、交易量等运营指标 Args: city (str, optional): 城市名如 Ho Chi Minh City Returns: str: JSON格式的设备汇总报告 try: if city and city not in CITIES: return json.dumps({ error: f未知城市 {city}, suggestion: f请使用以下城市名之一: {, .join(CITIES)} }, ensure_asciiFalse) target_cities [city] if city else CITIES all_devices [] for c in target_cities: for i in range(DEVICE_COUNT_PER_CITY): all_devices.append(_generate_device_data(c, i)) total len(all_devices) online sum(1 for d in all_devices if d[status] online) avg_success sum(d[scan_success_rate] for d in all_devices) / total report { region: city or Vietnam (All Cities), total_devices: total, online_rate: f{online/total*100:.1f}%, avg_scan_success: f{avg_success*100:.1f}%, total_transactions_today: sum(d[total_transactions] for d in all_devices), sample_devices: all_devices[:3] } return json.dumps(report, indent2, ensure_asciiFalse) except Exception as e: return json.dumps({ error: f设备状态获取失败: {str(e)}, suggestion: 请稍后重试或检查网络连接 }, ensure_asciiFalse)设计要点每城500台设备共1500台的规模源于智联工坊越南市场的真实铺货量在线率88%的设定模拟了真实IoT场景中设备因网络、电力等因素导致的离线率结构化错误返回errorsuggestion让Agent能理解并处理异常工具2越南盾汇率查询器tools/exchange_rate.pytool def get_vietnam_exchange_rate(base_currency: str CNY) - str: 功能描述获取越南盾VND兑指定货币的汇率及近期走势。 设计思路 1. 模拟汇率数据1 CNY ≈ 3400-3600 VND在合理区间内随机浮动 2. 生成过去7天的模拟历史数据展示上涨或下跌趋势 3. 支持 CNY 和 USD 两种基础货币 Args: base_currency (str): 基础货币CNY 或 USD默认 CNY Returns: str: JSON格式的汇率数据及历史趋势 try: if base_currency not in [CNY, USD]: return json.dumps({ error: f不支持的基础货币 {base_currency}, suggestion: 请使用 CNY 或 USD }, ensure_asciiFalse) base_rate 3500.0 current_rate round(random.uniform(base_rate - 100, base_rate 100), 2) # 生成7天历史数据 history [] for i in range(6, -1, -1): day_rate current_rate * (1 random.uniform(-0.03, 0.03)) history.append({ date: (datetime.now() - timedelta(daysi)).strftime(%Y-%m-%d), rate: round(day_rate, 2) }) result { base_currency: base_currency, target_currency: VND, current_rate: current_rate, trend: 上涨 if history[-1][rate] history[0][rate] else 下跌, history_7d: history, updated_at: datetime.now().isoformat() } return json.dumps(result, indent2, ensure_asciiFalse) except Exception as e: return json.dumps({ error: f汇率获取失败: {str(e)}, suggestion: 请稍后重试 }, ensure_asciiFalse)设计要点同时支持CNY和USD适配不同角色的决策需求财务看USD业务看CNY7天历史趋势让Agent能判断“上涨”或“下跌”而不仅仅是当前值工具3越南市场情报检索器tools/vietnam_news.py# 模拟新闻数据库 MOCK_NEWS_DB { payments: [{ title: 越南电子支付市场2026年预计增长25%, source: Vietnam Economic Times, date: 2026-07-10, summary: 越南央行数据显示2026年上半年电子支付交易额同比增长25%。 }], vending: [{ title: 胡志明市便利店密度超越新加坡新零售设备需求激增, source: Saigon Business Review, date: 2026-07-09, summary: 胡志明市便利店数量已超过新加坡自助终端设备需求旺盛。 }], general: [{ title: 越南2026年Q2 GDP增长6.2%制造业表现强劲, source: Vietnam Investment Review, date: 2026-07-07, summary: 越南经济持续复苏制造业与服务业成为主要增长引擎。 }] } tool def search_vietnam_market_intelligence(topic: str general) - str: 检索越南市场新闻与商业情报。 key TOPIC_MAP.get(topic, general) results MOCK_NEWS_DB.get(key, MOCK_NEWS_DB[general]) return json.dumps({ topic: topic, total_results: len(results), news: results, retrieved_at: datetime.now().isoformat() }, indent2, ensure_asciiFalse)设计要点主题分类支付、新零售、汇率、通用模拟真实情报系统的分类逻辑预留了未来对接真实新闻API的扩展接口工具4多语言报告生成器tools/report_generator.pytool def generate_market_report(device_summary: str, exchange_rate_data: str, news_data: str) - str: 功能描述生成越南市场情报报告Markdown格式。 设计思路 1. 整合设备数据、汇率数据、新闻数据 2. 生成中文报告主体并调用百度翻译API生成越南语摘要 3. 报告自动保存到 workspace/reports/ 目录 Returns: str: 报告保存路径 # 解析JSON提取关键信息 # 生成中文报告主体 # 调用翻译生成越南语摘要 # 保存Markdown文件并返回路径 return f报告已生成{filepath}设计要点Markdown格式便于人工阅读也便于后续转换为PDF或HTML百度翻译API集成体现“出海”场景的真实需求报告保存到workspace/reports/目录形成可追溯的历史文档四、Agent构建让AI学会“规划”而非“执行”4.1 Agent类型选择在C1中我们使用了CONVERSATIONAL_REACT_DESCRIPTION它支持单参数工具如calculate(35)。但在C2中部分工具需要多个参数。例如generate_market_report需要三个输入参数因此升级为STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION该类型支持多参数工具Agent会要求模型输出JSON格式的参数。4.2 System Prompt设计为了让Agent按照业务逻辑顺序执行我们在agent/prompts.py中定义了专用System PromptVIETNAM_MARKET_SYSTEM_PROMPT 你是一位拥有20年经验的物联网与海外市场运营专家。 你正在为智联工坊公司分析越南市场业务。 你的工作流程必须遵循 1. 当用户询问越南市场状况时首先调用 fetch_vietnam_device_status 获取设备运营数据 2. 根据设备数据中的异常主动调用 get_vietnam_exchange_rate 和 search_vietnam_market_intelligence 3. 综合所有数据调用 generate_market_report 生成结构化报告 重要原则 - 数据驱动先获取数据再做分析 - 按序执行必须按照 设备状态 → 汇率 → 新闻 → 报告 的顺序执行 4.3 Agent构建代码def create_agent(verbose: bool False): llm Ollama( modelMODEL_NAME, base_urlOLLAMA_BASE_URL, temperature0.1, # 调低温度提高决策稳定性 systemVIETNAM_MARKET_SYSTEM_PROMPT, ) tools [ fetch_vietnam_device_status, # 1. 先看设备 get_vietnam_exchange_rate, # 2. 再看汇率 search_vietnam_market_intelligence, # 3. 再看新闻 generate_market_report, # 4. 最后生成报告 ] memory ConversationBufferMemory( memory_keychat_history, return_messagesTrue, ) agent initialize_agent( tools, llm, agentAgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, memorymemory, verboseverbose, handle_parsing_errorsTrue, max_iterations15, return_intermediate_stepsTrue, # 关键参数提高解析稳定性 ) return agent4.4 关键参数说明参数值作用temperature0.1降低模型输出的随机性提高工具调用决策的稳定性max_iterations15防止Agent陷入无限循环15次迭代足以完成4步工具调用return_intermediate_stepsTrue返回中间步骤提高解析器对模型输出的容错能力五、运行测试Agent的“思考链”全记录启动Agent后输入查询越南盾汇率观察完整的思考链你: 查询越南盾汇率 Entering new AgentExecutor chain... Action: { action: get_vietnam_exchange_rate, action_input: { base_currency: CNY } } Observation: { base_currency: CNY, target_currency: VND, current_rate: 3506.57, trend: 上涨, history_7d: [ {date: 2026-07-08, rate: 3487.95}, {date: 2026-07-09, rate: 3530.38}, ... ] } Thought: 我已经获取了汇率数据用户需要的是查询结果我可以直接返回。 Final Answer: 当前越南盾兑人民币汇率为 3506.57趋势为上涨。关键观察Agent首先思考需要什么工具 → 决定调用get_vietnam_exchange_rate工具返回数据后Agent评估是否满足需求 → 直接返回结果整个过程符合ReAct模式思考→行动→观察→回答六、踩坑记录三个关键问题的解决坑1run() not supported when there is not exactly one output key现象启用return_intermediate_stepsTrue后agent.run(user_input)报错。❌ 错误: run not supported when there is not exactly one output key. Got [output, intermediate_steps].原因run()方法要求返回值只有一个output键而启用return_intermediate_steps后返回值包含output和intermediate_steps两个键。解决改用agent.invoke({input: user_input})[output]。# 修改前报错 response agent.run(user_input) # 修改后正常 result agent.invoke({input: user_input}) response result[output]经验LangChain官方已推荐invoke()替代run()C2的实践也印证了这一点。坑2Could not parse LLM output现象Agent在调用工具时偶尔输出格式不符合解析器的预期。Could not parse LLM output: Action: json {action: get_vietnam_exchange_rate, ...}**原因**Qwen2.5:7B作为开源模型输出的JSON偶尔会包含多余的markdown标记或文本。 **解决** - 将 temperature 从0.3降至0.1减少输出的随机性 - 启用 return_intermediate_stepsTrue增强解析器的容错能力 ### 坑3跨文件系统路径映射问题 **现象**在PyCharm中代码报“未解析的引用”但命令行运行正常。 **原因**项目代码在Windows文件系统/mnt/d/...而Python解释器在WSL中两者路径前缀不一致。 **解决**在PyCharm中配置路径映射Path Mappings将Windows路径映射到WSL路径。或采用方案二将项目代码迁移到WSL原生文件系统。 **经验**对于跨平台开发环境路径映射是绕不开的必修课。 ## 七、工程化实践V1.2代码规范的落地 在C2的开发过程中我同步升级了专栏的代码规范至 **V1.2版本**核心变化包括 ### 7.1 文件头模板 每个Python文件开头包含核心问题、解决方案推演、业务场景溯源 python # 制造数据与AI践行者老蒋 | CSDN: https://blog.csdn.net/javy21 # 文件名: config.py # 核心问题: 集中管理所有配置项 # 解决方案推演 (Why this way?): # 1. 方案选择: 使用 python-dotenv 加载 .env 文件 # 2. 关键设计: 所有路径使用 pathlib.Path确保跨平台兼容 # 3. 边界思考: 启动时校验关键配置缺失时给出友好警告 # 案例溯源: 智联工坊虚拟工厂 - 商用智能交互屏 项目 # 海外场景: 越南市场设备MQTT数据处理 7.2 AI Agent异常处理规范工具函数在异常时返回结构化错误而非抛出堆栈return json.dumps({ error: f设备状态获取失败: {str(e)}, suggestion: 请稍后重试或检查网络连接 }, ensure_asciiFalse)7.3 业务场景脱敏规范所有案例统一映射至“智联工坊”虚拟工厂体系杜绝真实企业信息泄露。八、总结与下篇预告总结通过C2的实践我们完成了从“单工具调用”到“多工具协同”的能力跃迁。核心收获如下多工具协同的本质是“任务拆解状态传递”Agent需要自主决定工具调用顺序并将中间结果传递给下游工具工具描述比工具实现更重要工具函数的名称、描述、参数说明直接影响模型调用的准确性参数调优是工程化的关键temperature0.1提升稳定性return_intermediate_stepsTrue增强解析容错工程化规范是长期输出的保障统一的文件头、异常处理、脱敏规范让代码真正可复用、可传播下篇预告《Agent记忆系统让AI从“金鱼脑”到“大象记忆”》短时记忆ConversationBufferMemory的原理与实现长时记忆用向量数据库构建Agent的“长期记忆”记忆管理策略总结、压缩、遗忘的工程实践在C2的越南市场场景中如何让Agent记住“上周已经生成过报告”敬请期待本文完整代码所有代码已在本地环境验证通过可直接运行关注收藏评论区【用LangChain构建越南市场情报系统】免费分享。专栏主页从RAG到Agent20年IT老兵的AI智能体实战笔记技术交流欢迎在评论区留言我会持续关注并回复。作者制造数据与AI践行者老蒋javy21博客制造数据与AI践行者老蒋-CSDN博客