在这里插入图片描述

  【个人主页:玄同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)。这种设计的优势在于:

  1. 接口统一:不管是提示词、大模型、链还是工具,都用同样的方法调用;
  2. 组合灵活:不同组件可以通过|运算符自由组合;
  3. 易于扩展:继承抽象基类实现核心方法即可定制自己的组件。

核心抽象层继承树(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核心作用:将PromptTemplateLLM组合,实现最基础的文本生成链。代码示例

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 的基类,定制属于自己的组件吧!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐