掌握 LangChain 的 Runnable:统一接口、链式组合与流式输出全解析

文章目录

    • [一、什么是 Runnable?------ LangChain 的"积木块"](#一、什么是 Runnable?—— LangChain 的“积木块”)
      • [Runnable 的核心能力](#Runnable 的核心能力)
    • [二、常见的 Runnable 实例](#二、常见的 Runnable 实例)
      • [1. **模型(Model)本身就是 Runnable**](#1. 模型(Model)本身就是 Runnable)
      • [2. **PromptTemplate:将变量拼成消息**](#2. PromptTemplate:将变量拼成消息)
      • [3. **Chain:用 `|` 拼接 Runnable(管道操作)**](#3. Chain:用 | 拼接 Runnable(管道操作))
      • [4. **自定义 Runnable:用函数包装**](#4. 自定义 Runnable:用函数包装)
    • [三、高级 Runnable:带状态与记忆](#三、高级 Runnable:带状态与记忆)
      • [1. **RunnableWithMessageHistory:会话记忆**](#1. RunnableWithMessageHistory:会话记忆)
      • [2. **RunnablePassthrough:透传 + 增强**](#2. RunnablePassthrough:透传 + 增强)
    • [四、Runnable 的底层机制](#四、Runnable 的底层机制)
    • [五、为什么 Runnable 如此重要?](#五、为什么 Runnable 如此重要?)
      • [1. **统一接口**](#1. 统一接口)
      • [2. **可组合性**](#2. 可组合性)
      • [3. **可观测性**](#3. 可观测性)
      • [4. **部署友好**](#4. 部署友好)
    • 六、实战:构建一个带记忆的问答机器人
    • 总结

LangChain 是当前最流行的 LLM(大语言模型)应用开发框架,其核心设计理念是 "可组合、可复用、可追踪" 。而这一切的基石,正是它的 Runnable 接口体系 。本文将从 Runnable 出发,深入浅出地介绍 LangChain 的核心思想与使用方式。


一、什么是 Runnable?------ LangChain 的"积木块"

在 LangChain 中,一切可执行的组件都是 Runnable

Runnable 不是一个具体类,而是一个抽象接口(Protocol),定义了如何处理输入、产生输出,并支持链式调用、批处理、流式响应等高级功能。

Runnable 的核心能力

能力 方法 说明
同步调用 .invoke(input, config=None, **kwargs) 单次输入 → 单次输出,最常用
异步调用 .ainvoke(input, config=None, **kwargs) 异步版本,适用于 async/await 环境
批量处理 .batch(inputs, config=None, **kwargs) 多输入 → 多输出,支持并行(如多用户请求)
异步批量 .abatch(inputs, config=None, **kwargs) 异步批量处理
流式输出 .stream(input, config=None, **kwargs) 逐块(chunk)返回生成内容,用于实时打字机效果
异步流式 .astream(input, config=None, **kwargs) 异步流式生成
流式批处理 .stream_log(input, config=None, **kwargs) 流式返回执行日志(含中间步骤,用于调试)
异步流式日志 .astream_log(input, config=None, **kwargs) 异步版本的流式日志

这些方法让所有组件行为统一,无论你用的是模型、提示词、工具还是自定义函数。


二、常见的 Runnable 实例

1. 模型(Model)本身就是 Runnable

python 复制代码
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o")
# llm 是一个 Runnable!

response = llm.invoke("你好!")  # 直接调用
  • 输入:strList[BaseMessage]
  • 输出:AIMessage

2. PromptTemplate:将变量拼成消息

python 复制代码
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个{role}助手"),
    ("human", "{input}")
])
# prompt 也是 Runnable!

messages = prompt.invoke({"role": "客服", "input": "订单没到"})
# 输出: [SystemMessage(...), HumanMessage(...)]
  • 输入:dict(键对应模板变量)
  • 输出:List[BaseMessage]

3. Chain:用 | 拼接 Runnable(管道操作)

python 复制代码
chain = prompt | llm  # 自动组合!

response = chain.invoke({"role": "诗人", "input": "写一首春天的诗"})
# 内部:dict → messages → AIMessage

这就是 LangChain 最强大的地方:像搭积木一样组合 AI 应用


4. 自定义 Runnable:用函数包装

python 复制代码
from langchain_core.runnables import RunnableLambda

def add_greeting(input_str: str) -> str:
    return f"你好!{input_str}"

greet_chain = RunnableLambda(add_greeting) | llm

response = greet_chain.invoke("今天天气如何?")

任何函数都可以变成 Runnable


三、高级 Runnable:带状态与记忆

1. RunnableWithMessageHistory:会话记忆

python 复制代码
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import InMemoryChatMessageHistory

def get_session_history(session_id: str):
    return InMemoryChatMessageHistory()

chain_with_memory = RunnableWithMessageHistory(
    chain,  # 底层 chain
    get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)

config = {"configurable": {"session_id": "user123"}}
response = chain_with_memory.invoke(
    {"input": "我是小明"}, 
    config=config
)
  • 自动加载历史、注入 prompt、保存新消息;
  • 实现多轮对话记忆。

2. RunnablePassthrough:透传 + 增强

python 复制代码
from langchain_core.runnables import RunnablePassthrough

# 在不改变输入的情况下,附加上下文
enriched_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
)

常用于 RAG(检索增强生成)场景。


四、Runnable 的底层机制

所有 Runnable 都继承自 RunnableSerializable,并实现 _invoke 等私有方法。但你无需关心这些,因为:

LangChain 的设计哲学是:关注"做什么",而不是"怎么做"。

当你写 prompt | model 时,LangChain 自动:

  1. prompt 的输出(消息列表)作为 model 的输入;
  2. 处理类型转换;
  3. 支持异步、流式、批处理等。

五、为什么 Runnable 如此重要?

1. 统一接口

无论是模型、工具、数据库查询还是自定义逻辑,都遵循同一套调用规范。

2. 可组合性

通过 | 运算符,轻松构建复杂 pipeline:

python 复制代码
retriever | prompt | llm | parser

3. 可观测性

配合 LangSmith,自动记录每一步的输入/输出、耗时、token 使用等。

4. 部署友好

整个 chain 可序列化为 JSON,便于部署到服务器或 Serverless 平台。


六、实战:构建一个带记忆的问答机器人

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.chat_history import InMemoryChatMessageHistory

# 1. 定义模型
llm = ChatOpenAI(model="gpt-4o-mini")

# 2. 定义带历史的 Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个 helpful AI 助手"),
    MessagesPlaceholder("history"),
    ("human", "{input}")
])

# 3. 构建 chain
chain = prompt | llm

# 4. 添加记忆
memory_store = {}

def get_history(session_id: str):
    if session_id not in memory_store:
        memory_store[session_id] = InMemoryChatMessageHistory()
    return memory_store[session_id]

chatbot = RunnableWithMessageHistory(
    chain,
    get_history,
    input_messages_key="input",
    history_messages_key="history"
)

# 5. 使用
config = {"configurable": {"session_id": "abc123"}}
print(chatbot.invoke({"input": "你好!"}, config).content)
print(chatbot.invoke({"input": "我刚才说了什么?"}, config).content)

全程只调用 .invoke(),背后自动处理记忆、拼接、调用。


总结

LangChain 的灵魂,就是 Runnable

它把 LLM 应用从"一次性脚本"提升为"可工程化系统"。理解 Runnable,就掌握了 LangChain 的钥匙。

  • 想快速原型?用 RunnableLambda 包装函数。
  • 想做 RAG?用 RunnablePassthrough 组合检索器。
  • 想支持多轮对话?用 RunnableWithMessageHistory
相关推荐
野犬寒鸦2 小时前
从零起步学习计算机操作系统:进程篇(知识扩展提升)
java·服务器·开发语言·后端·面试
新缸中之脑2 小时前
cmux多智能体管理工具
运维·服务器
超级大福宝2 小时前
集群中服务器的个数为什么最好是奇数个
服务器·分布式·后端
怕浪猫2 小时前
第3章 LangChain 核心抽象:Models 与 Messages
langchain·llm·ai编程
小璐资源网2 小时前
《Nginx缓存配置:浏览器缓存与服务器缓存实战》
服务器·nginx·缓存
2301_816374333 小时前
AutoBackupGuard 多服务器自动化备份与完整性校验系统
linux·运维·服务器·centos·自动化·github
袁小皮皮不皮3 小时前
【HCIA】第二章 ipv4协议以及子网划分与集合
linux·运维·服务器·网络·网络协议·tcp/ip·信息与通信
科技前瞻观察3 小时前
赋能智算升级|基于极海G32R501实时控制DSP MCU的AI服务器电源应用方案
服务器·人工智能·单片机
暴力求解3 小时前
Linux---ELF动态库加载
linux·运维·服务器