LangChain 核心类继承关系全解析:从抽象到实现的定制指南
【个人主页:玄同765】
大语言模型(LLM)开发工程师|中国传媒大学·数字媒体技术(智能交互与游戏设计)
深耕领域:大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调
技术栈:Python / LangChain/RAG(Dify+Redis+Milvus)| SQL/NumPy | FastAPI+Docker ️
工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案
「让AI交互更智能,让技术落地更高效」
欢迎技术探讨/项目合作! 关注我,解锁大模型与智能交互的无限可能!
LangChain 的强大之处在于其模块化、可扩展的设计—— 通过大量抽象基类定义统一接口,子类实现具体业务逻辑,让开发者可以像搭积木一样组合组件,也能轻松定制自己的功能。但要真正掌握 LangChain 的扩展能力,必须理解其核心类的继承关系和方法体系。
本文将从 LangChain 的核心抽象层出发,分模块梳理类的继承关系、核心方法,并结合实战示例讲解如何通过继承定制自己的组件,覆盖 LangChain 1.0 + 的最新 API 设计。
一、LangChain 的设计哲学:抽象基类 + 接口统一
LangChain 1.0 + 版本重构了核心架构,所有组件都围绕 **Runnable抽象基类 ** 构建,实现了统一的调用接口(invoke/batch/stream)。这种设计的优势在于:
- 接口统一:不管是提示词、大模型、链还是工具,都用同样的方法调用;
- 组合灵活:不同组件可以通过
|运算符自由组合; - 易于扩展:继承抽象基类实现核心方法即可定制自己的组件。
核心抽象层继承树(Mermaid 图)
graph TD
classDef abstract fill:#f9f,stroke:#333,stroke-width:2px;
classDef concrete fill:#fff,stroke:#333,stroke-width:1px;
object --> Runnable:::abstract
Runnable --> RunnableSerializable:::abstract
RunnableSerializable --> BasePromptTemplate:::abstract
RunnableSerializable --> BaseLanguageModel:::abstract
RunnableSerializable --> Chain:::abstract
RunnableSerializable --> BaseMemory:::abstract
RunnableSerializable --> BaseTool:::abstract
BasePromptTemplate --> PromptTemplate:::concrete
BasePromptTemplate --> ChatPromptTemplate:::concrete
BasePromptTemplate --> FewShotPromptTemplate:::concrete
BaseLanguageModel --> LLM:::abstract
BaseLanguageModel --> ChatModel:::abstract
LLM --> OpenAI:::concrete
ChatModel --> ChatOpenAI:::concrete
Chain --> LLMChain:::concrete
Chain --> RetrievalQA:::concrete
BaseMemory --> ConversationBufferMemory:::concrete
BaseMemory --> ConversationSummaryMemory:::concrete
BaseTool --> StructuredTool:::concrete
BaseTool --> PythonAstREPLTool:::concrete
二、核心抽象类:定义统一接口
1. Runnable:所有组件的根接口
继承关系:object → Runnable → RunnableSerializable核心作用:定义了所有 LangChain 组件必须实现的统一调用接口,是 LangChain 1.0 + 的核心设计。核心方法:
| 方法名 | 作用 | 参数说明 |
|---|---|---|
invoke(input, config=None) |
处理单个请求,返回结果 | input:输入数据;config:配置参数 |
batch(inputs, config=None, return_exceptions=False) |
批量处理多个请求 | inputs:输入列表;return_exceptions:是否返回异常而非抛出 |
stream(input, config=None) |
流式返回结果 | 适合大模型流式输出场景 |
ainvoke(input, config=None) |
异步处理单个请求 | 异步版本的invoke |
abatch(inputs, config=None, return_exceptions=False) |
异步批量处理 | 异步版本的batch |
astream(input, config=None) |
异步流式返回结果 | 异步版本的stream |
代码示例:查看Runnable的继承关系
import inspect
from langchain_core.runnables import Runnable
# 查看类的方法解析顺序(继承链)
print("Runnable继承链:", inspect.getmro(Runnable))
# 输出:(<class 'langchain_core.runnables.base.Runnable'>, <class 'object'>)
# 查看类的所有方法
print("Runnable核心方法:", [method for method in dir(Runnable) if not method.startswith('_')])
2. BaseLanguageModel:大模型的抽象基类
继承关系:RunnableSerializable → BaseLanguageModel核心作用:定义了大模型的统一接口,所有大模型组件(LLM/ChatModel)都继承自它。核心方法:
| 方法名 | 作用 |
|---|---|
generate(prompts, stop=None, callbacks=None, **kwargs) |
生成文本,处理多个提示词 |
invoke(input, config=None, stop=None, **kwargs) |
统一调用接口,处理单个请求 |
predict(text, stop=None, **kwargs) |
简化的文本生成方法(LLM 子类实现) |
predict_messages(messages, stop=None, **kwargs) |
简化的消息生成方法(ChatModel 子类实现) |
代码示例:定制自己的大模型组件
from langchain_core.language_models import BaseLanguageModel
from langchain_core.messages import BaseMessage
from typing import List, Dict, Any
class CustomLLM(BaseLanguageModel):
def generate(
self,
prompts: List[str],
stop: List[str] | None = None,
callbacks: Any = None,
**kwargs: Any,
) -> Any:
# 定制生成逻辑,这里返回模拟结果
from langchain_core.outputs import Generation, LLMResult
generations = [
Generation(text=f"模拟生成结果:{prompt}") for prompt in prompts
]
return LLMResult(generations=[generations])
def invoke(
self,
input: str | List[BaseMessage],
config: Any = None,
stop: List[str] | None = None,
**kwargs: Any,
) -> str | BaseMessage:
if isinstance(input, str):
return f"模拟生成结果:{input}"
else:
from langchain_core.messages import AIMessage
return AIMessage(content=f"模拟生成结果:{input[-1].content}")
# 使用定制的LLM
custom_llm = CustomLLM()
result = custom_llm.invoke("请写一句广告语")
print(result) # 输出:模拟生成结果:请写一句广告语
三、提示词模块:从模板到定制
1. 提示词类继承树
graph TD
BasePromptTemplate --> PromptTemplate
BasePromptTemplate --> ChatPromptTemplate
ChatPromptTemplate --> FewShotChatMessagePromptTemplate
BasePromptTemplate --> FewShotPromptTemplate
BasePromptTemplate --> PipelinePromptTemplate
2. 核心类详解
(1)BasePromptTemplate:提示词模板的基类
继承关系:RunnableSerializable → BasePromptTemplate核心方法:
| 方法名 | 作用 |
|---|---|
format(**kwargs) |
填充模板变量,返回字符串提示词 |
invoke(input, config=None) |
统一调用接口,返回格式化后的提示词 |
partial(**kwargs) |
预填充部分变量,返回新的模板 |
validate_template() |
验证模板的有效性 |
(2)PromptTemplate:文本提示词模板
继承关系:BasePromptTemplate → PromptTemplate核心作用:处理纯文本提示词,支持参数化模板。代码示例:
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=["topic"],
template="请写一篇关于{topic}的技术博客,不少于500字。"
)
print(prompt.format(topic="LangChain继承关系"))
# 输出:请写一篇关于LangChain继承关系的技术博客,不少于500字。
(3)ChatPromptTemplate:对话提示词模板
继承关系:BasePromptTemplate → ChatPromptTemplate核心作用:处理对话场景的提示词,支持SystemMessage/HumanMessage等消息类型。代码示例:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
chat_prompt = ChatPromptTemplate.from_messages([
SystemMessage(content="你是一名专业的技术博客作者"),
HumanMessage(content="请写一篇关于{topic}的技术博客,不少于500字。")
])
messages = chat_prompt.invoke({"topic": "LangChain继承关系"})
print(messages)
(4)FewShotPromptTemplate:少样本提示词模板
继承关系:BasePromptTemplate → FewShotPromptTemplate核心作用:添加示例到提示词中,实现少样本学习,提升模型输出的一致性。
四、链与记忆:组合与状态管理
1. 链模块继承树
graph TD
Chain --> LLMChain
Chain --> RetrievalQA
Chain --> ConversationChain
RunnableSerializable --> RunnableSequence # 1.0+新增的链式组合
(1)Chain:链的抽象基类
继承关系:RunnableSerializable → Chain核心作用:定义了链的统一接口,链是多个组件的组合(如 PromptTemplate + LLM)。核心方法:
| 方法名 | 作用 |
|---|---|
run(inputs, callbacks=None, **kwargs) |
运行链,返回结果(0.1.x 版本常用) |
invoke(input, config=None, **kwargs) |
统一调用接口(1.0 + 版本推荐) |
predict(callbacks=None, **kwargs) |
简化的预测方法,类似run |
(2)LLMChain:最基础的链
继承关系:Chain → LLMChain核心作用:将PromptTemplate与LLM组合,实现最基础的文本生成链。代码示例:
from langchain_core.chains import LLMChain
from langchain_openai import OpenAI
llm = OpenAI(temperature=0.7)
prompt = PromptTemplate(
input_variables=["topic"],
template="请写一句关于{topic}的广告语。"
)
chain = LLMChain(llm=llm, prompt=prompt)
result = chain.invoke({"topic": "智能手表"})
print(result) # 输出:{'topic': '智能手表', 'text': '腕间智能,掌控未来。'}
2. 记忆模块继承树
graph TD
BaseMemory --> ConversationBufferMemory
BaseMemory --> ConversationSummaryMemory
BaseMemory --> ConversationBufferWindowMemory
BaseMemory --> VectorStoreRetrieverMemory
(1)BaseMemory:记忆的抽象基类
继承关系:RunnableSerializable → BaseMemory核心作用:定义了记忆组件的统一接口,负责存储和加载对话历史。核心方法:
| 方法名 | 作用 |
|---|---|
load_memory_variables(inputs, callbacks=None) |
加载记忆变量 |
save_context(inputs, outputs, callbacks=None) |
保存对话上下文 |
clear() |
清空记忆 |
(2)ConversationBufferMemory:简单对话记忆
继承关系:BaseMemory → ConversationBufferMemory核心作用:直接存储所有对话历史,适合简单的多轮对话场景。代码示例:
from langchain_core.memory import ConversationBufferMemory
from langchain_core.chains import ConversationChain
from langchain_openai import ChatOpenAI
memory = ConversationBufferMemory()
chain = ConversationChain(
llm=ChatOpenAI(model_name="gpt-3.5-turbo"),
memory=memory,
verbose=True
)
chain.invoke({"input": "你好,我叫张三"})
chain.invoke({"input": "我想了解LangChain的继承关系"})
chain.invoke({"input": "我刚才问了什么问题?"}) # 模型会记住之前的问题
五、工具与代理:扩展大模型能力
1. 工具模块继承树
graph TD
BaseTool --> StructuredTool
BaseTool --> PythonAstREPLTool
BaseTool --> ShellTool
(1)BaseTool:工具的抽象基类
继承关系:RunnableSerializable → BaseTool核心作用:定义了工具的统一接口,让大模型可以调用外部工具。核心方法:
| 方法名 | 作用 |
|---|---|
run(input, callbacks=None, **kwargs) |
运行工具,返回结果 |
invoke(input, config=None, **kwargs) |
统一调用接口 |
name |
工具名称(属性) |
description |
工具描述(属性),大模型通过描述理解工具功能 |
(2)StructuredTool:结构化工具
继承关系:BaseTool → StructuredTool核心作用:将 Python 函数封装为工具,支持结构化输入输出。代码示例:定制自己的工具
from langchain_core.tools import StructuredTool
def add_numbers(a: int, b: int) -> int:
"""计算两个数的和"""
return a + b
# 将函数封装为工具
tool = StructuredTool.from_function(add_numbers)
result = tool.invoke({"a": 10, "b": 20})
print(result) # 输出:30
2. 代理模块继承树
graph TD
RunnableSerializable --> AgentExecutor
BaseSingleActionAgent --> ZeroShotAgent
BaseSingleActionAgent --> ConversationalAgent
AgentExecutor --> ZeroShotAgentExecutor
(1)AgentExecutor:代理的执行器
继承关系:RunnableSerializable → AgentExecutor核心作用:协调 Agent 与工具的交互,负责决策调用哪个工具、处理工具返回结果。核心方法:
| 方法名 | 作用 |
|---|---|
invoke(input, config=None, **kwargs) |
统一调用接口,处理用户请求 |
run(input, callbacks=None, **kwargs) |
简化的运行方法 |
(2)ZeroShotAgent:零样本代理
继承关系:BaseSingleActionAgent → ZeroShotAgent核心作用:无需示例即可理解并调用工具,适合大多数场景。代码示例:创建一个可以调用工具的代理
from langchain_core.agents import AgentExecutor, ZeroShotAgent
from langchain_core.tools import Tool
from langchain_openai import OpenAI
llm = OpenAI(temperature=0)
# 定义工具
def add_numbers(a: int, b: int) -> int:
return a + b
tools = [
Tool(
name="AddNumbers",
func=add_numbers,
description="用于计算两个数的和,输入是两个整数"
)
]
# 创建Agent
prefix = "你是一名专业的计算器,擅长使用工具解决数学问题。"
suffix = "请根据用户的问题选择合适的工具。"
prompt = ZeroShotAgent.create_prompt(
tools,
prefix=prefix,
suffix=suffix,
input_variables=["input", "agent_scratchpad"]
)
agent = ZeroShotAgent(llm_chain=LLMChain(llm=llm, prompt=prompt), tools=tools)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 运行代理
result = agent_executor.invoke({"input": "计算100加200的和"})
print(result) # 输出:{'input': '计算100加200的和', 'output': '300'}
六、实战:通过继承定制 LangChain 组件
1. 定制提示词模板
from langchain_core.prompts import BasePromptTemplate
from typing import List, Dict
class CustomPromptTemplate(BasePromptTemplate):
"""定制的提示词模板,自动添加版权信息"""
def format(self, **kwargs) -> str:
base_prompt = f"请写一篇关于{kwargs['topic']}的技术博客。"
# 添加版权信息
return f"{base_prompt}\n\n版权所有:{kwargs['copyright']}"
def invoke(self, input: Dict, **kwargs) -> str:
return self.format(**input)
# 使用定制模板
prompt = CustomPromptTemplate(input_variables=["topic", "copyright"])
result = prompt.invoke({"topic": "LangChain继承关系", "copyright": "张三"})
print(result)
2. 定制记忆组件
from langchain_core.memory import BaseMemory
from typing import List, Dict, Any
class CustomMemory(BaseMemory):
"""定制的记忆组件,只存储最近3轮对话"""
def __init__(self, window_size: int = 3):
super().__init__()
self.window_size = window_size
self.chat_history: List[Dict[str, str]] = []
def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
return {"chat_history": self.chat_history}
def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:
self.chat_history.append({"input": inputs["input"], "output": outputs["output"]})
# 只保留最近window_size轮对话
if len(self.chat_history) > self.window_size:
self.chat_history = self.chat_history[-self.window_size:]
def clear(self) -> None:
self.chat_history = []
# 使用定制记忆
memory = CustomMemory(window_size=2)
chain = ConversationChain(
llm=ChatOpenAI(model_name="gpt-3.5-turbo"),
memory=memory,
verbose=True
)
# 多轮对话测试
chain.invoke({"input": "你好,我叫张三"})
chain.invoke({"input": "我想了解LangChain的继承关系"})
chain.invoke({"input": "我叫什么名字?"}) # 模型会记住
chain.invoke({"input": "我刚才问了什么技术问题?"}) # 模型会记住
chain.invoke({"input": "请介绍一下Python的继承关系"}) # 超过window_size,最早的对话会被遗忘
chain.invoke({"input": "我叫什么名字?"}) # 模型会忘记之前的名字
七、总结:LangChain 继承设计的核心优势
1. 抽象与实现分离
- 抽象基类(如
Runnable/BaseLanguageModel)定义统一接口,子类实现具体逻辑; - 开发者只需关注接口,无需关心具体实现,降低了组件之间的耦合。
2. 可扩展性强
- 通过继承抽象基类,可以轻松定制自己的组件(如定制提示词、大模型、记忆等);
- 符合开闭原则:对扩展开放,对修改关闭。
3. 接口统一
- 所有组件都实现了
Runnable接口,用统一的invoke/batch方法调用; - 组件之间可以自由组合,用
|运算符构建复杂的大模型应用。
4. 向后兼容
- LangChain 1.0 + 版本保留了旧版本的核心类(如
LLMChain/ConversationBufferMemory),并让它们实现了Runnable接口; - 旧代码可以平滑升级到新版本。
理解 LangChain 的类继承关系,不仅能帮助你更好地理解内部实现,更能让你轻松定制自己的组件,构建出更符合业务需求的大模型应用。现在就动手尝试继承 LangChain 的基类,定制属于自己的组件吧!
更多推荐


所有评论(0)