LangChain教程:RunnabLeLambda组件让普通函数能融入 LangChain 的链式调用 作者:马育民 • 2026-02-27 08:46 • 阅读:10002 # 介绍 `RunnableLambda` 是 LangChain 中用于 **将普通 Python 函数包装成「可运行组件(Runnable)」** 的工具,让普通函数能无缝融入 LangChain 的链式调用(`|` 语法)中。 简单来说: - 普通函数无法直接用 `|` 和 Prompt、LLM、解析器等组件串联; - 用 `RunnableLambda` 包装后,函数就变成了 Runnable 类型,能和其他组件一起组成链式流程。 # 用法 ### 方式1 传入普通函数 ``` RunnableLambda(fun) ``` ##### 参数解释 - fun:普通函数 ### 方式2 传入lambda函数 ``` RunnableLambda(lambda 函数) ``` # 例子1-传入普通函数 ``` from langchain_core.prompts import ChatPromptTemplate from langchain_community.chat_models.tongyi import ChatTongyi from langchain_core.runnables import RunnableLambda from dotenv import load_dotenv # 加载 .env 文件,并放入到环境变量中 load_dotenv() # 定义普通 Python 函数,提取LLM返回的文本内容 def process_resp(resp) -> str: """ 调用 .content,直接返回字符串 """ return resp.content # 用 RunnableLambda 包装函数 rl = RunnableLambda(process_resp) # 定义模板 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个温柔的小学数学老师,回答问题时用“亲”、“小朋友”,并且简短回答问题,回答问题不要用markdown格式"), ("human", "计算过程:{msg}") ]) model = ChatTongyi(model="qwen3-max") # 串联时,最后使用 rl chain = prompt | model | rl while True: """ 输入:3x+5=20,x 等于多少? """ question = input("请输入:") # 调用stream向模型提问,返回 generator类型 res = chain.stream({ "msg": question }) # 流式输出 for chunk in res: # ※※※ 不需要调用 .content ※※※ print(chunk, end="", flush=True) print("\n----回答结束-------\n") ``` # 例子2-传入lambda函数 ``` from langchain_core.prompts import ChatPromptTemplate from langchain_community.chat_models.tongyi import ChatTongyi from langchain_core.runnables import RunnableLambda from dotenv import load_dotenv # 加载 .env 文件,并放入到环境变量中 load_dotenv() # 创建 RunnableLambda 对象,传入 lambda 函数 rl = RunnableLambda(lambda resp: resp.content) # 定义模板 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个温柔的小学数学老师,回答问题时用“亲”、“小朋友”,并且简短回答问题,回答问题不要用markdown格式"), ("human", "计算过程:{msg}") ]) model = ChatTongyi(model="qwen3-max") # 串联时,最后使用 rl chain = prompt | model | rl while True: """ 输入:3x+5=20,x 等于多少? """ question = input("请输入:") # 调用stream向模型提问,返回 generator类型 res = chain.stream({ "msg": question }) # 流式输出 for chunk in res: # ※※※ 不需要调用 .content ※※※ print(chunk, end="", flush=True) print("\n----回答结束-------\n") ``` # 案例3-转成JSON 通过定义函数,将返回结果转成 JSON: ``` from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate from langchain_community.chat_models.tongyi import ChatTongyi from langchain_core.runnables import RunnableLambda from dotenv import load_dotenv import json # 定义普通 Python 函数,提取LLM返回的文本内容 def json_parse(resp) -> dict: """安全的JSON解析函数:捕获解析错误""" text = resp.content try: return json.loads(text) except json.JSONDecodeError: print(f"❌ JSON解析失败,原始文本:{text}") return {"code": 500} # 返回默认值,避免链中断 # 用 RunnableLambda 包装函数 rl = RunnableLambda(json_parse) # 第一步:定义示例模板(告诉 AI 示例的格式) example_template = """ 名称:{name} 屏幕:{screen} CPU:{cpu} 5G:{5G} """ example_prompt = PromptTemplate.from_template(example_template) # 第二步:准备示例(列表+字典格式,每个字典是一个示例) examples = [ {"name": "iPhone 17 Pro Max", "screen": "6.9英寸", "cpu": "A19 Pro(3纳米制程)", "5G": "支持"} ] # 第三步:1.定义开头的引导语 prefix = "请按照以下格式返回指定手机的配置(参考示例格式):" # 第三步:2.定义问AI的问题 # ※※※必须明确指出输出格式※※※ # suffix = "现在请生成 {name} 的手机配置,必须严格按照指定格式输出JSON:" suffix = "现在请生成 {name} 的手机配置,必须严格按照指定格式输出JSON,不要markdown:" # 第四步:组装 FewShotPromptTemplate few_shot_prompt = FewShotPromptTemplate( prefix=prefix, # 开头的引导语 example_prompt=example_prompt, # 示例的格式模板 examples=examples, # 要展示给 AI 的示例 suffix=suffix, # 问AI的问题(包含动态变量) input_variables=["name"], # 最终要传入的动态变量(这里是城市名) ) # 加载 .env 文件,并放入到环境变量中 load_dotenv() # 创建模型对象 model = ChatTongyi(model="qwen-max") # 串联模板、模型、json输出解析器(| 运算符) chain = few_shot_prompt | model | rl # 因为要将结果转成json,所以要获取到全部返回结果才能转换,所以不能用流式输出,否则格式错乱 resp = chain.invoke({"name": "iphone11"}) print("---------大模型回答--------------------") print("res类型", type(resp)) print(resp) ``` ##### 代码解释1 ``` def json_parse(resp) -> dict: """安全的JSON解析函数:捕获解析错误""" text = resp.content try: return json.loads(text) except json.JSONDecodeError: print(f"❌ JSON解析失败,原始文本:{text}") return {"code": 500} # 返回默认值,避免链中断 ``` ##### 代码解释2 执行下面代码,返回的是 markdown 格式,转成JSON会报错: ``` suffix = "现在请生成 {name} 的手机配置,必须严格按照指定格式输出JSON:" ``` 报错如下: ``` ❌ JSON解析失败,原始文本:``json { "名称": "iPhone 11", "屏幕": "6.1英寸", "CPU": "A13 Bionic", "5G": "不支持" } `` ---------大模型回答-------------------- res类型 {'code': 500} Process finished with exit code 0 ``` ##### 代码解释3 执行下面代码,返回的是标准 JSON 格式,正常转成JSON: ``` suffix = "现在请生成 {name} 的手机配置,必须严格按照指定格式输出JSON,不要markdown:" ``` 执行结果: ``` ---------大模型回答-------------------- res类型 {'名称': 'iPhone 11', '屏幕': '6.1英寸', 'CPU': 'A13 Bionic(7纳米制程)', '5G': '不支持'} ``` # 关键特性与使用场景 ### 1. 支持不同类型的输入输出 `RunnableLambda` 不限制函数的输入输出类型,可处理: - 字符串、数字、字典等基础类型; - LangChain 内置类型(如 `ChatMessage`、`BaseMessage`); - 自定义类实例。 ### 2. 处理链式调用中的「中间加工」 这是最常用的场景:在链式流程中插入自定义逻辑,比如: - 清洗 LLM 返回的文本(去除多余字符、修正格式); - 转换数据类型(如将字符串转为字典/列表); - 过滤/提取数据(如从结构化结果中取指定字段); - 记录日志、统计耗时等辅助操作。 ### 3. 支持异步函数 如果你的函数是异步的(`async def` 定义),`RunnableLambda` 会自动适配,无需额外处理: ```python import asyncio # 定义异步函数 async def async_process(text: str) -> str: await asyncio.sleep(0.1) # 模拟异步操作(如网络请求) return text.lower() # 包装异步函数 async_runnable = RunnableLambda(async_process) # 异步调用 async def main(): result = await async_runnable.ainvoke("HELLO ASYNC") print("✅ 异步调用结果:", result) # 输出:hello async asyncio.run(main()) ``` ### 4. 错误处理 可在包装的函数中添加异常捕获,保证链式调用的稳定性: ```python def safe_json_parse(text: str) -> dict: """安全的JSON解析函数:捕获解析错误""" try: return json.loads(text) except json.JSONDecodeError: print(f"❌ JSON解析失败,原始文本:{text}") return {"keywords": []} # 返回默认值,避免链中断 # 包装后融入链,即使解析失败也不会崩溃 safe_parse_runnable = RunnableLambda(safe_json_parse) ``` ### 进阶:带上下文的函数(RunnableLambda + Config) 如果需要在函数中获取链式调用的上下文(如 `run_id`、`tags`),可通过 `config` 参数获取: ```python def with_context(text: str, config: dict) -> str: """函数接收第二个参数:config(链式调用的上下文)""" run_id = config.get("run_id", "未知ID") return f"[运行ID:{run_id}] {text}" # 包装时指定接收config runnable_with_context = RunnableLambda(with_context, takes_config=True) # 调用时传入config result = runnable_with_context.invoke( "测试上下文", config={"run_id": "123456"} ) print("✅ 带上下文的函数结果:", result) # 输出:[运行ID:123456] 测试上下文 ``` # 总结 1. `RunnableLambda` 的核心作用是**将普通Python函数包装为LangChain的Runnable组件**,使其能融入链式调用; 2. 主要用于链式流程中的「自定义中间处理」(如数据清洗、格式转换、数据提取); 3. 支持同步/异步函数,兼容任意输入输出类型,可添加错误处理保证链的稳定性。 简单来说,`RunnableLambda` 是「普通Python函数」和「LangChain链式调用」之间的桥梁,让你能灵活插入自定义逻辑,而不用受限于LangChain内置组件。 原文出处:http://malaoshi.top/show_1GW2qz81mZAA.html