langchain_core.runnables.chain
详解
langchain_core.runnables.chain
是 LangChain 框架中用于将 Python 函数转换为可运行对象(Runnable)的装饰器函数。本文详细介绍其功能、参数、使用方法、实际应用及注意事项,确保内容条理清晰、易于理解。
1. 概述
1.1 什么是 chain
装饰器?
langchain_core.runnables.chain
是一个装饰器函数,位于 langchain_core.runnables.base
模块,用于将普通的 Python 函数转换为 LangChain 的 Runnable
对象。Runnable
是 LangChain 生态系统的核心组件,支持同步、异步、批处理和流式处理等操作。通过 @chain
装饰器,开发者可以将自定义逻辑无缝集成到 LangChain 的工作流中,与其他组件(如提示模板、语言模型、输出解析器)组合成复杂的处理链。
该装饰器通过自动设置函数名称并追踪依赖项,简化了自定义 Runnable
的创建过程。它在 langchain-core
0.2.14 版本中引入,广泛应用于数据处理管道、实时应用和高并发场景。
1.2 与其他组件的关系
- 与
@tool
装饰器:前文讨论的langchain_core.tools.tool
用于创建工具型Runnable
,专注于语言模型调用外部功能;而chain
更适合封装通用逻辑,如数据预处理或后处理。 - 与
InjectedToolArg
:chain
可用于工具调用链中注入运行时参数,例如为工具提供动态输入。 - 与
RunnableSequence
和RunnableParallel
:chain
创建的Runnable
可通过|
运算符或.pipe()
方法与其他Runnable
组成顺序或并行处理链。
1.3 核心功能
- 自动转换:将函数转换为
Runnable
,名称默认为函数名。 - 依赖追踪:记录函数中调用的其他
Runnable
作为依赖项,便于调试。 - 灵活支持:兼容同步函数、异步函数、生成器和异步生成器。
- LCEL 集成:支持 LangChain Expression Language (LCEL),通过
|
或.pipe()
构建复杂链。 - 调试支持:与 LangSmith 等工具配合,提供执行跟踪和调试功能。
2. 使用方法
@chain
装饰器通过简单的方式将函数转换为 Runnable
。以下是不同场景下的使用示例:
2.1 同步函数
将普通函数转换为 Runnable
:
from langchain_core.runnables import chain
@chain
def add_one(x: int) -> int:
"""将输入加一"""
return x + 1
- 调用方式:
add_one.invoke(5)
返回 6。 - 组合链:
from langchain_core.runnables import RunnableLambda sequence = add_one | RunnableLambda(lambda x: x * 2) print(sequence.invoke(5)) # 输出 12
2.2 流式处理函数
使用生成器函数支持流式输出:
@chain
def generate_numbers(n: int):
"""生成从 0 到 n-1 的数字"""
for i in range(n):
yield i
- 调用方式:
for chunk in generate_numbers.stream(3): print(chunk)
输出 0、1、2。
2.3 异步函数
支持异步逻辑,提高并发性能:
import asyncio
from langchain_core.runnables import chain
@chain
async def async_add_one(x: int) -> int:
"""异步将输入加一"""
await asyncio.sleep(1) # 模拟异步操作
return x + 1
- 调用方式:
await async_add_one.ainvoke(5)
返回 6。
2.4 综合示例
结合提示模板和语言模型,展示复杂场景:
from langchain_core.runnables import chain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
@chain
def greet_user(fields):
"""生成个性化问候语"""
prompt = PromptTemplate.from_template("Hello, {name}!")
llm = OpenAI()
formatted = prompt.invoke(**fields)
for chunk in llm.stream(formatted):
yield chunk
- 调用方式:
for chunk in greet_user.stream({"name": "Alice"}): print(chunk)
输出流式问候语。
2.5 结合 InjectedToolArg
结合 InjectedToolArg
,在工具调用中注入运行时参数:
from langchain_core.runnables import chain
from langchain_core.tools import tool, InjectedToolArg
from typing import Annotated, List
@tool
def update_favorite_pets(pets: List[str], user_id: Annotated[str, InjectedToolArg]) -> None:
"""更新用户的收藏宠物"""
user_to_pets[user_id] = pets # 假设的存储
@chain
def inject_user_id(input):
"""注入用户 ID 到工具调用"""
tool_call = input["tool_call"]
user_id = input["user_id"]
tool_call_copy = tool_call.copy()
tool_call_copy["args"]["user_id"] = user_id
return {"tool_call": tool_call_copy}
# 组合链
chain = inject_user_id | update_favorite_pets
chain.invoke({"tool_call": {"name": "update_favorite_pets", "args": {"pets": ["dog"]}}, "user_id": "123"})
3. 参数与签名
chain
装饰器的签名如下:
langchain_core.runnables.base.chain(func: Callable[[Input], Output]) -> Runnable[Input, Output]
3.1 参数
参数 | 类型 | 描述 |
---|---|---|
func | Callable | 要装饰的函数,接受输入并返回输出。 |
支持的函数类型:
- 同步函数:
Callable[[Input], Output]
- 异步函数:
Callable[[Input], Coroutine[Any, Any, Output]]
- 生成器函数:
Callable[[Input], Iterator[Output]]
- 异步生成器函数:
Callable[[Input], AsyncIterator[Output]]
3.2 返回值
返回值 | 类型 | 描述 |
---|---|---|
Runnable | Runnable[Input, Output] | 支持 LangChain 标准接口的可运行对象。 |
4. 核心方法
chain
装饰器生成的 Runnable
继承自 RunnableSerializable
,支持以下标准方法:
方法 | 描述 | 输入 | 输出 |
---|---|---|---|
invoke | 同步调用,处理单个输入。 | input: Input, config: Optional[RunnableConfig] | Output |
ainvoke | 异步调用。 | input: Input, config: Optional[RunnableConfig] | Output |
batch | 同步批量处理多个输入。 | inputs: List[Input], config: Optional[RunnableConfig | List[RunnableConfig]] | List[Output] |
abatch | 异步批量处理。 | inputs: List[Input], config: Optional[RunnableConfig | List[RunnableConfig]] | List[Output] |
stream | 同步流式输出。 | input: Input, config: Optional[RunnableConfig] | Iterator[Output] |
astream | 异步流式输出。 | input: Input, config: Optional[RunnableConfig] | AsyncIterator[Output] |
astream_events | 异步流式事件,需 langchain-core>=0.2.29 。 | input: Input, config: Optional[RunnableConfig], version: Literal['v1', 'v2'] | AsyncIterator[StreamEvent] |
这些方法使 chain
创建的 Runnable
能够灵活适应不同场景。
5. 实际应用
chain
装饰器在以下场景中广泛使用:
- 数据处理管道:组合数据预处理、模型推理和后处理。例如,格式化用户输入、调用语言模型、解析输出。
- 流式应用:如实时聊天机器人,逐步生成响应。例如,使用生成器函数流式输出模型响应。
- 异步任务:在高并发场景下提高性能。例如,异步处理多个用户请求。
- 工具调用注入:结合
InjectedToolArg
,为工具调用注入运行时参数。 - 自定义逻辑:将特定业务逻辑封装为
Runnable
,与 LangChain 组件集成。
示例:复杂数据处理管道
from langchain_core.runnables import chain
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
@chain
def format_input(data: dict) -> dict:
"""格式化输入数据"""
return {"question": data["input"].upper()}
prompt = ChatPromptTemplate.from_template("Answer: {question}")
model = ChatOpenAI()
parser = StrOutputParser()
chain = format_input | prompt | model | parser
result = chain.invoke({"input": "hello"}) # 输出模型对 "HELLO" 的回答
6. 最佳实践
- 类型清晰:确保函数的输入和输出类型与链中其他
Runnable
的预期类型兼容。 - 文档字符串:为函数提供详细的文档字符串,便于调试和维护。
- 流式处理:对于实时输出的场景,使用生成器函数支持
stream
方法。 - 异步优化:在高并发场景下,优先使用异步函数以提高性能。
- 版本检查:确保使用
langchain-core>=0.2.14
,通过pip install -qU langchain
安装。 - 调试工具V:复杂链使用 LangSmith 等工具进行跟踪和调试。
7. 注意事项与限制
- 输入输出兼容性:函数的输入和输出需与链中其他
Runnable
的预期类型匹配,否则可能导致运行时错误。 - 异步环境:异步函数需在支持
asyncio
的环境中运行。 - 生成器格式:流式函数需正确使用
yield
确保输出逐块生成。 - 版本依赖:某些功能(如
astream_events
)需langchain-core>=0.2.29
。 - 调试复杂性:复杂链可能需要 LangSmith 等工具进行跟踪和调试。
8. 结论
langchain_core.runnables.chain
是一个强大而灵活的装饰器函数,通过将普通 Python 函数转换为 Runnable
对象,简化了自定义逻辑与 LangChain 生态系统的集成。它支持同步、异步、生成器和异步生成器函数,适用于数据处理管道、流式应用、异步任务和工具调用注入等场景。开发者应遵循最佳实践,确保类型兼容性和版本要求,以构建高效、可维护的 LangChain 应用。