RunnableLangChain 的“万能接口”在 LangChain 的世界里Runnable是一个统一的、标准的执行接口。所有能够“被调用、被组合、被传输”的组件无论是模型ChatTongyi、提示模板ChatPromptTemplate、输出解析器StrOutputParser、链Chain甚至是整个 LangGraph 图都实现了Runnable接口。一句话定义Runnable是 LangChain 表达语言LCEL的基石它定义了一个“如何执行一个任务”的通用契约。任何实现了Runnable的对象都可以用统一的 API 去调用它并可以用管道符|去和另一个Runnable串联。为什么需要 Runnable解决了什么问题在Runnable出现之前LangChain 中存在LLMChain、ConversationChain、RetrievalQA等多种“硬编码”的 Chain 类它们各自的调用方式各不相同无法统一组合。Runnable提供了一套标准化的接口使得所有组件可以无缝组合LCEL。所有组件支持统一的调用方式invoke、stream、batch。所有组件天然可观测可与 LangSmith 集成。所有组件可被包装和增强如RunnableWithMessageHistory。Runnable 的核心方法任何实现了Runnable的对象都至少实现了以下三个核心方法方法作用适用场景invoke(input, configNone)同步执行返回完整结果。常规单次调用。ainvoke(input, configNone)异步执行返回完整结果。异步环境如 FastAPI。stream(input, configNone)同步流式执行逐个产出结果。需要逐步输出长文本时。astream(input, configNone)异步流式执行逐个产出结果。异步流式输出。batch(inputs, configNone)批量执行返回结果列表。并发处理多个输入。abatch(inputs, configNone)异步批量执行。高并发场景。所有*async*方法是*sync*方法的异步版本前缀a代表async。哪些东西是 Runnable几乎一切组件类型示例模型ChatTongyi、ChatOpenAI、TongyiLLM提示模板PromptTemplate、ChatPromptTemplate、MessagesPlaceholder输出解析器StrOutputParser、PydanticOutputParser、JsonOutputParser检索器Chroma.as_retriever()返回的Retriever对象向量库Chroma本身直接调用工具tool装饰的函数如get_weather链所有用 Agentcreate_react_agent返回的图编译后GraphStateGraph.compile()返回的图自定义函数用RunnableLambda包装的任意函数如何创建一个 Runnable1. 最直接用|管道符组合 LCEL 链chainprompt|model|str_parserchain自动成为一个RunnableSequence支持所有 Runnable 方法。2. 用RunnableLambda包装普通函数fromlangchain_core.runnablesimportRunnableLambdadefmy_func(x):returnx.upper()runnable_funcRunnableLambda(my_func)# 然后可以放进链里chainprompt|model|runnable_func|str_parser3. 用RunnableParallel并行执行fromlangchain_core.runnablesimportRunnableParallel# 同时执行两个任务返回字典结果parallel_chainRunnableParallel(answerchain1,contextchain2)Runnable 的核心原则1.输入类型决定输出类型Runnable是类型安全的。例如ChatPromptTemplate接受dict包含变量值输出PromptValueChatModel接受PromptValue输出AIMessage。如果类型不匹配|管道会报错。2.配置config是可传递的在调用invoke(input, config...)时config可以携带metadata、tags、callbacks、max_concurrency等参数这些会贯穿整个链的执行过程特别适合可观测性LangSmith和限流。3.所有 Runnable 都可绑定回调fromlangchain_core.callbacksimportStdOutCallbackHandler chain.invoke(input,config{callbacks:[StdOutCallbackHandler()]})这样会打印链中每一步的执行日志极其有助于调试。Runnable 与 LangGraph 的关系LangGraph 中编译后的graph本身就是一个Runnable因此你可以像调用普通链一样graph.invoke(input)或graph.stream(input)。把graph作为子节点嵌入到更大的 LCEL 链中prompt | graph | str_parser。给graph挂载回调、配置thread_id等。利用astream_events获取更细粒度的事件这是 LangGraph 对Runnable接口的扩展。这也是为什么 LangGraph 与 LangChain 无缝集成它本质上是在 LangChain 的Runnable体系之上增加了“状态图”的编排能力。Runnable 在面试中的高频追问Q1RunnableSequence和普通的Chain有什么区别ARunnableSequence是 LCEL 方式的链它是Runnable接口的统一实现而传统Chain如LLMChain是硬编码类无法用|灵活组合。LangChain 官方推荐弃用旧Chain全面转向 LCEL。Q2invoke和stream的区别是什么Ainvoke是一次性返回完整结果stream是逐步产出结果生成器适合长文本流式输出。两者都是Runnable的标准方法所有组件都可选支持。Q3batch和abatch的优势是什么A可以批量处理多个输入且自动并发执行提升吞吐量。比如同时处理 10 条用户消息batch会比循环调用快数倍。Q4自定义Runnable应该怎么做A通常不需要显式实现Runnable只需用RunnableLambda包装函数若需要更复杂的逻辑如状态管理可继承Runnable并实现invoke、stream等方法。总结Runnable是 LangChain 生态的“基石接口”它统一了所有组件的执行方式定义了invoke、stream、batch三大核心方法并通过 LCEL|实现了组件的无限组合。无论是提示、模型、解析器、工具、检索器还是 LangGraph 图最终都归一为同一个Runnable接口这是 LangChain 能够保持高度灵活性和扩展性的根本原因。理解Runnable就理解了 LangChain 的“哲学”。