LangChain实战:如何用Tools和Routing让AI自动调用外部API(附天气查询完整代码)
LangChain高级应用构建智能API路由系统的实战指南1. 理解LangChain工具与路由机制的核心价值在现代AI应用开发中让语言模型具备调用外部API的能力已成为提升系统实用性的关键。LangChain通过其Tools和Routing机制为开发者提供了一套优雅的解决方案。不同于简单的函数调用这套系统实现了基于语义理解的智能路由决策。核心优势语义路由模型能根据用户输入的上下文自动选择最合适的工具简化集成通过装饰器快速将现有API封装为LangChain可识别的工具类型安全结合Pydantic实现输入参数的严格校验灵活扩展支持任意第三方服务的无缝接入实际开发中我们经常遇到这样的场景用户询问上海现在的天气如何系统需要自动识别这是天气查询需求选择天气API工具提取地理位置参数最终返回结构化的天气信息。传统实现需要大量硬编码逻辑而LangChain让这一切变得智能化。提示在开始编码前建议先规划好工具集的设计明确每个工具的职责边界和适用场景2. 构建你的第一个LangChain工具让我们从创建一个天气查询工具开始体验LangChain工具化的完整流程。2.1 基础工具定义首先安装必要依赖pip install langchain openai python-dotenv requests创建.env文件存储API密钥OPENAI_API_KEY你的密钥 WEATHER_API_KEY天气服务密钥基础工具实现from langchain.agents import tool import requests from pydantic import BaseModel, Field class WeatherInput(BaseModel): latitude: float Field(..., description查询地点的纬度) longitude: float Field(..., description查询地点的经度) tool(args_schemaWeatherInput) def get_current_weather(latitude: float, longitude: float) - str: 获取指定坐标的实时天气数据 api_url https://api.weatherapi.com/v1/current.json params { key: os.getenv(WEATHER_API_KEY), q: f{latitude},{longitude}, aqi: no } response requests.get(api_url, paramsparams) data response.json() return f{data[location][name]}当前天气{data[current][condition][text]}温度{data[current][temp_c]}°C2.2 工具的高级配置为提升工具可靠性我们可以添加以下增强功能错误处理改进try: response requests.get(api_url, paramsparams, timeout10) response.raise_for_status() data response.json() except requests.exceptions.RequestException as e: return f天气查询失败{str(e)}缓存机制from functools import lru_cache lru_cache(maxsize100) def get_current_weather(latitude: float, longitude: float) - str: # 原有实现工具验证测试print(get_current_weather.run({latitude: 31.23, longitude: 121.47})) # 输出上海当前天气晴朗温度28°C3. 实现智能路由系统单一工具的应用场景有限真正的价值在于多工具协同工作时的智能路由。3.1 多工具集成让我们再添加一个知识查询工具tool def search_knowledge(query: str) - str: 从知识库中检索相关信息 # 实际项目中可接入Elasticsearch等搜索引擎 knowledge_base { LangChain: 一个用于开发语言模型应用的框架, LLM: 大语言模型的简称 } return knowledge_base.get(query, 未找到相关信息)工具注册表tools [get_current_weather, search_knowledge]3.2 路由逻辑实现核心路由函数from langchain.schema.agent import AgentFinish def route_action(result): if isinstance(result, AgentFinish): return result.return_values[output] tool_mapping {tool.name: tool for tool in tools} selected_tool tool_mapping[result.tool] return selected_tool.run(result.tool_input)完整执行链构建from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser model ChatOpenAI(temperature0).bind(functionstools) prompt ChatPromptTemplate.from_messages([ (system, 你是一个智能助手可以回答天气和知识问题), (user, {input}) ]) chain prompt | model | OpenAIFunctionsAgentOutputParser() | route_action3.3 路由效果测试天气查询场景response chain.invoke({input: 东京现在的天气怎样}) print(response)知识查询场景response chain.invoke({input: 什么是LangChain}) print(response)混合场景处理response chain.invoke({input: 先告诉我纽约的天气再解释下LLM})4. 生产环境最佳实践将原型系统转化为生产级应用需要考虑更多因素。4.1 性能优化策略工具并行化from concurrent.futures import ThreadPoolExecutor def parallel_route(result): if isinstance(result, AgentFinish): return result.return_values[output] with ThreadPoolExecutor() as executor: future executor.submit(tool_mapping[result.tool].run, result.tool_input) return future.result()限流控制from ratelimit import limits, sleep_and_retry sleep_and_retry limits(calls10, period60) def get_current_weather(latitude: float, longitude: float) - str: # 原有实现4.2 监控与日志添加详细日志记录import logging logging.basicConfig(levellogging.INFO) def route_action(result): logging.info(fRouting decision: {result}) # 原有逻辑性能指标收集from time import perf_counter def timed_tool(func): def wrapper(*args, **kwargs): start perf_counter() result func(*args, **kwargs) duration perf_counter() - start logging.info(fTool {func.__name__} executed in {duration:.2f}s) return result return wrapper4.3 安全加固措施输入验证增强from pydantic import validator class WeatherInput(BaseModel): latitude: float Field(..., ge-90, le90) longitude: float Field(..., ge-180, le180) validator(latitude, longitude) def round_coordinates(cls, v): return round(v, 4)敏感数据过滤def sanitize_output(text: str) - str: patterns [r\b\d{3}[-.]?\d{3}[-.]?\d{4}\b] # 电话号码模式 for pattern in patterns: text re.sub(pattern, [REDACTED], text) return text5. 高级应用场景拓展基础功能实现后我们可以探索更复杂的应用模式。5.1 工具组合工作流实现多工具串联执行def query_weather_and_suggest(location: str): # 步骤1地理编码获取坐标 coords geocode_tool.run(location) # 步骤2查询天气 weather get_current_weather.run(coords) # 步骤3生成建议 suggestion suggestion_tool.run(weather) return suggestion5.2 动态工具加载基于配置文件的工具管理# tools_config.yaml tools: - name: weather module: weather_tool class: GetCurrentWeather params: api_key: ${WEATHER_API_KEY} - name: knowledge module: knowledge_tool class: KnowledgeSearch动态加载实现import yaml from importlib import import_module def load_tools(config_path): with open(config_path) as f: config yaml.safe_load(f) tools [] for tool_config in config[tools]: module import_module(tool_config[module]) tool_class getattr(module, tool_config[class]) tools.append(tool_class(**tool_config.get(params, {}))) return tools5.3 用户上下文感知维护对话上下文from typing import Dict, Any from langchain.schema import BaseMemory class CustomMemory(BaseMemory): def __init__(self): self.store: Dict[str, Any] {} def load_memory_variables(self, inputs: Dict[str, Any]) - Dict[str, Any]: return self.store def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) - None: self.store.update(outputs)在链中使用记忆from langchain.chains import ConversationChain conversation ConversationChain( llmmodel, memoryCustomMemory(), promptprompt )在实际项目中这种技术架构已经成功应用于多个场景。某金融客服系统通过动态工具路由将用户查询智能分发给不同的业务处理模块响应速度提升了40%。关键是要确保每个工具保持单一职责同时建立清晰的错误处理机制。