LangChain 最核心的扩展能力自定义工具把任意 Python 函数包装成 LLM 能调用的工具自定义链灵活组装你的业务逻辑不是简单的Prompt | LLM一、自定义工具Custom Tools1. 什么是自定义工具简单来说自定义工具就是把你的 Python 函数包装成 LLM 能理解、能自主调用的工具。比如你写一个天气查询函数 → 包装成工具 → LLM 能自主调用查天气你写一个数据库查询函数 → 包装成工具 → LLM 能自主查数据库你写一个文件读写函数 → 包装成工具 → LLM 能自主读写文件2. 自定义工具的 3 个核心要素1tool装饰器把普通 Python 函数变成 LangChain 工具的 “魔法装饰器”。2清晰的 docstring最重要这是LLM 的 “工具使用说明书”LLM 完全靠看 docstring 来判断这个工具是做什么的什么时候用这个工具参数是什么返回什么docstring 写得越清楚LLM 越会正确调用工具3正确的参数和返回值参数要明确类型返回值要是字符串方便 LLM 理解。二、实战自定义天气查询工具我们用OpenWeatherMap 免费 API来做天气查询工具稳定、免费、国内可访问。1. 准备工作1获取 OpenWeatherMap API Key访问 OpenWeatherMap 官网注册账号免费登录后进入「My API Keys」复制你的 API Key2安装依赖pip install -U langchain langchain-openai langchain-community python-dotenv requests三、完整代码自定义天气工具 自定义链 ReAct Agentimport os import requests from dotenv import load_dotenv # LangChain 相关 from langchain_core.tools import tool from langchain_core.runnables import RunnableLambda, RunnablePassthrough from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain.agents import AgentExecutor, create_react_agent from langchain_core.callbacks import StdOutCallbackHandler # 加载环境变量 load_dotenv() # 配置 OPENWEATHER_API_KEY os.getenv(OPENWEATHER_API_KEY) # 天气 API Key DOUBAO_API_KEY os.getenv(DOUBAO_API_KEY) # 初始化 LLM必须用支持工具调用的模型 llm ChatOpenAI( api_keyDOUBAO_API_KEY, base_urlhttps://ark.cn-beijing.volces.com/api/v3, modeldoubao-pro-32k, temperature0.01, ) # 第一部分自定义天气查询工具 tool def get_weather(city: str) - str: 【天气查询专用工具】查询指定城市的实时天气信息 当用户询问天气、温度、湿度、风速等气象信息时必须调用此工具 :param city: 城市名称支持中文如“北京”或英文如“Beijing” :return: 实时天气信息的字符串包括温度、湿度、天气描述、风速 base_url https://api.openweathermap.org/data/2.5/weather params { q: city, appid: OPENWEATHER_API_KEY, units: metric, # 摄氏度 lang: zh_cn # 中文描述 } try: response requests.get(base_url, paramsparams, timeout10) response.raise_for_status() data response.json() # 解析天气数据 weather_desc data[weather][0][description] temp data[main][temp] humidity data[main][humidity] wind_speed data[wind][speed] city_name data[name] return ( f【{city_name} 实时天气】\n f天气{weather_desc}\n f温度{temp}℃\n f湿度{humidity}%\n f风速{wind_speed} m/s ) except requests.exceptions.RequestException as e: return f天气查询失败{str(e)} except KeyError: return 未找到该城市的天气信息请检查城市名称是否正确 # 第二部分自定义链Custom Chain # 自定义链的两种方式 # 1. RunnableLambda最简单适合简单逻辑 # 2. 继承 Runnable最灵活适合复杂逻辑 # 例子1用 RunnableLambda 做一个简单的“文本长度统计链” def count_text_length(text: str) - str: 统计文本长度的自定义函数 return f文本长度{len(text)} 个字符 # 包装成 Runnable length_counter RunnableLambda(count_text_length) # 例子2组装一个完整的自定义链翻译 长度统计 translation_prompt ChatPromptTemplate.from_template(把下面的文本翻译成英文{text}) translation_chain translation_prompt | llm | StrOutputParser() # 自定义链先翻译再统计长度 custom_chain ( {text: RunnablePassthrough()} | translation_chain | (lambda x: {original: x, length: count_text_length(x)}) ) # 第三部分把自定义工具加入 ReAct Agent # 工具列表把天气工具加进去 tools [get_weather] # ReAct 提示词 prompt ChatPromptTemplate.from_messages([ (system, 你是一个强大的智能助手能通过调用工具解决问题。 核心规则 1. 严格按照「Thought → Action → Observation」的格式执行 2. 当用户询问天气时必须调用 get_weather 工具 3. 只有获取了足够的信息才能输出 Final Answer 4. 禁止编造信息 可用工具{tools} 工具名称{tool_names} ), (user, {input}), (placeholder, {agent_scratchpad}), ]) # 创建 ReAct Agent agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, # 开启详细日志 handle_parsing_errorsTrue, callbacks[StdOutCallbackHandler()], ) # 主程序 def main(): print( LangChain 自定义工具 自定义链 Agent ) print(1. 测试自定义天气工具) print(2. 测试自定义链翻译 长度统计) print(3. 测试 ReAct Agent自主调用天气工具) print(输入 q 退出\n) while True: choice input(请选择功能1/2/3/q).strip() if choice.lower() q: print( 再见) break # 测试1自定义天气工具 if choice 1: city input(请输入城市名称).strip() result get_weather.invoke(city) print(f\n️ 天气查询结果\n{result}\n) # 测试2自定义链 elif choice 2: text input(请输入要翻译的中文文本).strip() result custom_chain.invoke(text) print(f\n 翻译结果{result[original]}) print(f {result[length]}\n) # 测试3ReAct Agent elif choice 3: query input(请输入你的问题比如“北京今天天气怎么样”).strip() result agent_executor.invoke({input: query}) print(f\n Agent 最终回答{result[output]}\n) else: print(⚠️ 无效选择请重新输入\n) if __name__ __main__: main()四、.env文件配置DOUBAO_API_KEY你的豆包APIKey OPENWEATHER_API_KEY你的OpenWeatherMapAPIKey五、代码核心部分详解1. 自定义天气工具tool装饰器tool def get_weather(city: str) - str: 【天气查询专用工具】查询指定城市的实时天气信息 当用户询问天气、温度、湿度、风速等气象信息时必须调用此工具 :param city: 城市名称支持中文如“北京”或英文如“Beijing” :return: 实时天气信息的字符串包括温度、湿度、天气描述、风速 # ... 具体实现tool把函数变成工具docstring 极其重要LLM 完全靠它判断什么时候用工具参数和返回值明确方便 LLM 理解2. 自定义链RunnableLambdadef count_text_length(text: str) - str: return f文本长度{len(text)} 个字符 # 包装成 Runnable length_counter RunnableLambda(count_text_length)RunnableLambda把普通 Python 函数变成 LangChain 可调用的链可以和其他链用|操作符串联3. 把工具加入 Agenttools [get_weather] agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue)把自定义工具加入tools列表Agent 就能自主判断什么时候调用工具了六、运行效果演示测试 1自定义天气工具plaintext请选择功能1/2/3/q1 请输入城市名称北京 ️ 天气查询结果 【北京 实时天气】 天气晴 温度22℃ 湿度45% 风速2.1 m/s测试 2自定义链请选择功能1/2/3/q2 请输入要翻译的中文文本你好世界 翻译结果Hello, World 文本长度12 个字符测试 3ReAct Agent请选择功能1/2/3/q3 请输入你的问题比如“北京今天天气怎么样”北京今天天气怎么样 Entering new AgentExecutor chain... Thought: 用户询问北京的天气我需要调用 get_weather 工具查询北京的天气。 Action: get_weather(北京) Observation: 【北京 实时天气】... Thought: 我已经获取了北京的天气信息现在可以给出最终答案了。 Final Answer: 北京今天的天气是晴温度22℃湿度45%风速2.1 m/s。 Finished chain. Agent 最终回答北京今天的天气是晴温度22℃湿度45%风速2.1 m/s。七、总结自定义工具的核心tool装饰器 清晰的 docstring自定义链的核心RunnableLambda或继承RunnableAgent 调用工具的核心把工具加入tools列表LLM 会自主判断