零基础学AI大模型之LangChain核心:Runnable接口底层实现

大家好,我是工藤学编程 🦉 一个正在努力学习的小博主,期待你的关注
实战代码系列最新文章😉 C++实现图书管理系统(Qt C++ GUI界面版)
SpringBoot实战系列🐷 【SpringBoot实战系列】SpringBoot3.X 整合 MinIO 存储原生方案
分库分表 分库分表之实战-sharding-JDBC分库分表执行流程原理剖析
消息队列 深入浅出 RabbitMQ-RabbitMQ消息确认机制(ACK)
AI大模型 零基础学AI大模型之MultiQueryRetriever多查询检索全解析

前情摘要

1、零基础学AI大模型之读懂AI大模型
2、零基础学AI大模型之从0到1调用大模型API
3、零基础学AI大模型之SpringAI
4、零基础学AI大模型之AI大模型常见概念
5、零基础学AI大模型之大模型私有化部署全指南
6、零基础学AI大模型之AI大模型可视化界面
7、零基础学AI大模型之LangChain
8、零基础学AI大模型之LangChain六大核心模块与大模型IO交互链路
9、零基础学AI大模型之Prompt提示词工程
10、零基础学AI大模型之LangChain-PromptTemplate
11、零基础学AI大模型之ChatModel聊天模型与ChatPromptTemplate实战
12、零基础学AI大模型之LangChain链
13、零基础学AI大模型之Stream流式输出实战
14、零基础学AI大模型之LangChain Output Parser
15、零基础学AI大模型之解析器PydanticOutputParser
16、零基础学AI大模型之大模型的"幻觉"
17、零基础学AI大模型之RAG技术
18、零基础学AI大模型之RAG系统链路解析与Document Loaders多案例实战
19、零基础学AI大模型之LangChain PyPDFLoader实战与PDF图片提取全解析
20、零基础学AI大模型之LangChain WebBaseLoader与Docx2txtLoader实战
21、零基础学AI大模型之RAG系统链路构建:文档切割转换全解析
22、零基础学AI大模型之LangChain 文本分割器实战:CharacterTextSplitter 与 RecursiveCharacterTextSplitter 全解析
23、零基础学AI大模型之Embedding与LLM大模型对比全解析
24、零基础学AI大模型之LangChain Embedding框架全解析
25、零基础学AI大模型之嵌入模型性能优化
26、零基础学AI大模型之向量数据库介绍与技术选型思考
27、零基础学AI大模型之Milvus向量数据库全解析
28、零基础学AI大模型之Milvus核心:分区-分片-段结构全解+最佳实践
29、零基础学AI大模型之Milvus部署架构选型+Linux实战:Docker一键部署+WebUI使用
30、零基础学AI大模型之Milvus实战:Attu可视化安装+Python整合全案例
31、零基础学AI大模型之Milvus索引实战
32、零基础学AI大模型之Milvus DML实战
33、零基础学AI大模型之Milvus向量Search查询综合案例实战
33、零基础学AI大模型之新版LangChain向量数据库VectorStore设计全解析
34、零基础学AI大模型之相似度Search与MMR最大边界相关搜索实战
35、零基础学AI大模型之LangChain整合Milvus:新增与删除数据实战
36、零基础学AI大模型之LangChain+Milvus实战:相似性搜索与MMR多样化检索全解析
37、零基础学AI大模型之LangChain Retriever
38、零基础学AI大模型之MultiQueryRetriever多查询检索全解析


本文章目录

零基础学AI大模型之LangChain核心:Runnable接口底层实现

一、Runnable接口:LangChain组件的"统一通行证"

Runnable接口是LangChain框架中所有可执行组件的核心抽象,相当于给所有功能模块制定了一套统一的"交互协议"。

无论是Prompt模板、大模型调用、输出解析器,还是自定义的数据处理逻辑,只要实现了Runnable接口,就能无缝融入LangChain的生态,参与链式调用。

其核心定义来自langchain_core.runnables模块,所有组件通过实现它的标准方法,实现了"即插即用"的模块化能力。


二、为什么必须懂Runnable?四大核心价值

1. 统一接口,消除兼容性壁垒

所有LangChain组件(PromptTemplate、ChatModel、OutputParser等)都遵循同一套Runnable规范,无需关心组件内部实现,只需关注输入输出格式。

2. 灵活组合,简化链式编排

通过管道符|就能快速串联多个Runnable组件,形成复杂的业务流程,类似数据流处理的方式,大幅降低代码复杂度。

3. 动态配置,提升系统鲁棒性

支持运行时参数绑定、组件热替换,还能通过with_retry()等机制实现错误恢复,让系统更灵活、更稳定。

4. 原生优化,适配高并发场景

内置异步方法(ainvoke)和并行处理能力(RunnableParallel),无需额外开发就能应对高并发、大数据量的使用场景。


三、底层实现原理:管道符|背后的秘密

1. 管道符的本质:__or__方法重写

LangChain的管道符|并非Python原生功能,而是通过重写Runnable类的__or__魔术方法实现的。

当我们写下prompt | model | output_parser时,实际是触发了__or__方法,将多个Runnable组件传入RunnableSequence的构造函数,最终形成一个线性执行的链。

2. 核心数据结构:RunnableSequence

RunnableSequence是Runnable的核心子类,专门负责管理顺序执行的组件链。

它会将串联的组件存储在内部的steps列表中,执行时按顺序遍历列表,调用每个组件的对应方法(如invoke),并将上一个组件的输出作为下一个组件的输入,形成单向数据流。

3. 延迟执行机制

链的构建过程(prompt | model | output_parser)仅定义了组件间的逻辑关系,不会立即执行。

只有当调用invokestream等执行方法时,才会触发整个链路的运行,支持动态传入参数和运行时配置。

4. invoke方法源码核心逻辑

python 复制代码
def invoke(
    self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any
) -> Output:
    # 遍历所有步骤,顺序执行
    try:
        for i, step in enumerate(self.steps):
            # 为每个步骤标记子任务,便于日志和回调
            config = patch_config(
                config, callbacks=run_manager.get_child(f"seq:step:{i + 1}")
            )
            with set_config_context(config) as context:
                # 第一个步骤传入原始输入和kwargs,后续步骤传入上一步输出
                if i == 0:
                    input = context.run(step.invoke, input, config, **kwargs)
                else:
                    input = context.run(step.invoke, input, config)
        return input
    except Exception as e:
        # 错误处理逻辑
        raise e

核心逻辑总结:

  • 按顺序执行steps列表中的每个组件
  • 为每个步骤分配独立的配置和回调,便于追踪
  • 第一个组件接收完整输入,后续组件接收前序输出
  • 统一的错误捕获机制,确保链路稳定性

四、Runnable核心方法:四种执行模式全覆盖

Runnable接口定义了四种核心执行方法,适配不同的业务场景,所有实现类都需遵守该规范。

方法名 执行模式 适用场景 核心特点
invoke() 同步执行 单次调用、简单链路 阻塞等待完整结果,代码简洁
ainvoke() 异步执行 高并发场景、异步系统集成 非阻塞,支持异步await,提升吞吐量
stream() 流式输出 实时响应、大文本生成 逐块返回结果,减少等待时间
batch() 批量执行 数据集处理、批量推理 一次性处理多个输入,效率更高

方法使用示例(核心代码)

python 复制代码
# 1. invoke():同步单次执行
result = chain.invoke({"question": "LangChain是什么?"})

# 2. ainvoke():异步执行(需在async函数中使用)
async def async_run():
    result = await chain.ainvoke({"question": "LangChain是什么?"})

# 3. stream():流式输出
for chunk in chain.stream({"question": "LangChain是什么?"}):
    print(chunk, end="", flush=True)

# 4. batch():批量执行
inputs = [
    {"question": "LangChain是什么?"},
    {"question": "Runnable接口的作用?"},
    {"question": "如何串联LangChain组件?"}
]
results = chain.batch(inputs)

五、关键子类:Runnable的"功能扩展包"

除了基础的Runnable接口,LangChain还提供了多个实用子类,覆盖常见的业务场景,无需重复造轮子。

1. RunnableSequence:顺序执行链

  • 核心作用:实现组件的线性串联,是|管道符的默认实现
  • 适用场景:按固定顺序执行的流程(如Prompt→模型→解析器)
  • 特点:单向数据流,步骤不可跳过

2. RunnableBranch:条件路由链

  • 核心作用:根据输入条件选择不同的执行分支
  • 适用场景:多场景适配(如不同问题类型对应不同Prompt)
  • 特点:支持动态分支选择,类似if-elif-else逻辑

3. RunnableParallel:并行执行链

  • 核心作用:多个组件并行执行,互不依赖
  • 适用场景:多任务同时处理(如同时查询多个数据源)
  • 特点:提升执行效率,结果以字典形式返回

4. RunnablePassthrough:数据透传组件

  • 核心作用:透传输入数据,或添加固定参数
  • 适用场景:补充额外上下文、保持输入结构不变
  • 特点:不修改核心数据,仅做扩展或透传

六、实战:基于Runnable构建完整链路

下面通过一个完整案例,展示Runnable接口的实际应用,实现"Prompt构建→模型调用→结果解析"的全流程。

1. 环境准备

bash 复制代码
pip install langchain langchain-openai pydantic

2. 完整代码

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from langchain_core.runnables import RunnableSequence

# 1. 定义输出格式(Pydantic模型)
class AnswerSchema(BaseModel):
    question: str = Field(description="用户的原始问题")
    answer: str = Field(description="大模型的回答内容")
    summary: str = Field(description="回答的核心摘要(不超过50字)")

# 2. 初始化组件(均实现Runnable接口)
prompt = ChatPromptTemplate.from_messages([
    ("system", "请详细回答用户问题,并提炼核心摘要"),
    ("human", "{question}")
])
model = ChatOpenAI(model="gpt-3.5-turbo", api_key="你的API密钥")
parser = PydanticOutputParser(pydantic_object=AnswerSchema)

# 3. 构建Runnable链(两种方式等价)
# 方式1:管道符串联(推荐)
chain = prompt | model | parser

# 方式2:显式创建RunnableSequence
chain = RunnableSequence(steps=[prompt, model, parser])

# 4. 调用Runnable方法执行
if __name__ == "__main__":
    # 同步执行
    result = chain.invoke({"question": "Runnable接口的核心价值是什么?"})
    print("同步执行结果:")
    print(f"问题:{result.question}")
    print(f"回答:{result.answer}")
    print(f"摘要:{result.summary}\n")

    # 流式执行
    print("流式执行结果:")
    for chunk in chain.stream({"question": "Runnable接口有哪些核心方法?"}):
        if chunk:
            print(chunk, end="", flush=True)

    # 批量执行
    print("\n\n批量执行结果:")
    inputs = [
        {"question": "invoke方法的作用?"},
        {"question": "stream方法的适用场景?"}
    ]
    results = chain.batch(inputs)
    for idx, res in enumerate(results, 1):
        print(f"\n第{idx}个结果:")
        print(f"问题:{res.question}")
        print(f"摘要:{res.summary}")

3. 执行结果说明

  • 同步执行(invoke):一次性返回完整的解析后结果,结构清晰
  • 流式执行(stream):逐块返回解析后的对象,适合实时展示
  • 批量执行(batch):一次性处理多个输入,效率高于多次invoke

七、总结:Runnable是LangChain的"灵魂"

Runnable接口通过统一的抽象定义,解决了LangChain组件的兼容性和组合性问题,是整个框架的核心基石。

核心要点回顾:

  1. Runnable是所有组件的统一接口,定义了标准的执行方法
  2. 管道符|本质是__or__方法重写,背后由RunnableSequence支撑
  3. 四大核心方法(invoke/ainvoke/stream/batch)覆盖不同执行场景
  4. 丰富的子类(RunnableBranch/RunnableParallel等)降低复杂逻辑开发成本

理解Runnable的底层实现,能帮助我们更灵活地构建自定义组件、优化链路性能,为复杂大模型应用打下坚实基础。


如果这篇文章对你有帮助,别忘了点赞关注哦!😊

相关推荐
凯子坚持 c11 小时前
深度解析 MySQL 与 MCP 集成:从环境构建到 AI 驱动的数据交互全流程
人工智能·mysql·交互
219911 小时前
Embabel:JVM上的AI Agent框架深度技术分析
java·jvm·人工智能·spring·ai·开源
SelectDB技术团队11 小时前
面向 Agent 的高并发分析:Doris vs. Snowflake vs. ClickHouse
数据仓库·人工智能·科技·apache·知识图谱
风途知识百科11 小时前
化工厂防爆气象站
网络·人工智能
KKKlucifer11 小时前
2025 AI 安全攻防战:智能体崛起下的 “守护与突围
人工智能·安全
盖雅工场11 小时前
物流排班“自研”陷阱?如何破解物流行业排班与合规难题?
大数据·人工智能
WADesk---瓜子11 小时前
AI 文本检测工具在内容行业的应用:从原创度判断到内容安全审查的全流程解析
人工智能·安全
渡我白衣11 小时前
AI应用层革命(六)——智能体的伦理边界与法律框架:当机器开始“做决定”
人工智能·深度学习·神经网络·机器学习·计算机视觉·自然语言处理·语音识别
独自归家的兔12 小时前
大模型通义千问3-VL-Plus - 视觉理解
java·人工智能·intellij-idea