看langchain理解python中的链式调用

背景

先看两段langchain调用模型的代码

python 复制代码
def chat():
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一名资深的开发工程师,请回答用户提的问题"),
        ("human", "{user_input}"),
    ])
    llm = ChatOllama(
        model="qwen3-vl:8b",
        temperature=0,
    )
    ai_msg = llm.invoke(prompt.format_messages(user_input="请给我一个关于机器学习的例子"))
    print(ai_msg)

def chat_chain_call():
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一名资深的开发工程师,请回答用户提的问题"),
        ("human", "{user_input}"),
    ])
    llm = ChatOllama(
        model="qwen3-vl:8b",
        temperature=0,
    )
    # 创建链
    chain=prompt | llm
    # 调用
    ai_msg = chain.invoke({"user_input": "请给我一个关于机器学习的例子"})
    print(ai_msg)

核心代码为

python 复制代码
	# 创建链
    chain=prompt | llm
    # 调用
    ai_msg = chain.invoke({"user_input": "请给我一个关于机器学习的例子"})
    print(ai_msg)

这是 LangChain (或类似现代 Python AI 框架,如 LlamaIndex、Haystack)中典型的**链式调用(Chaining)**写法。其核心原理是 利用 Python 的 __or__ 魔术方法(即 | 运算符重载)实现管道式(pipeline)组合

下面从原理到实现一步步解释:


🔧 一、链式调用的本质:函数/对象的组合(Composition)

目标:将多个处理步骤(如 prompt 模板 → LLM → 解析器)像水管一样串起来,数据自动从前一个流向后一个。

传统写法:

python 复制代码
ai_msg = llm.invoke(prompt.format_messages(user_input="请给我一个关于机器学习的例子"))
print(ai_msg)

链式写法(更简洁、可复用、可嵌套):

python 复制代码
	# 创建链
    chain=prompt | llm
    # 调用
    ai_msg = chain.invoke({"user_input": "请给我一个关于机器学习的例子"})
    print(ai_msg)

⚙️ 二、技术原理:__or__ 运算符重载 + Runnable 协议

在 LangChain 中(v0.1+),所有可组合的组件(如 PromptTemplate, LLM, RunnableLambda 等)都继承自 Runnable 基类。

关键机制:

  1. Runnable 类定义了 __or__ 方法

    python 复制代码
    class Runnable:
        def __or__(self, other):
            return RunnableSequence(first=self, second=other)
  2. | 运算符被重载为返回一个新的 RunnableSequence 对象

    • prompt | llm → 返回 RunnableSequence(prompt, llm)
  3. RunnableSequence.invoke() 实现自动流水线执行

    python 复制代码
    def invoke(self, input, config=None):
        output = self.first.invoke(input, config)
        return self.second.invoke(output, config)

所以 chain.invoke(...) 实际上是依次调用每个组件的 .invoke() 方法,并把前一个的输出作为后一个的输入。


🧩 三、数据流示例

python 复制代码
chain = prompt | llm
result = chain.invoke({"text": "Thank you"})

执行过程:

  1. prompt.invoke({"text": "Thank you"})

    → 返回格式化后的字符串,如 "Classify: Thank you -> Positive"

  2. llm.invoke("Classify: Thank you -> Positive")

    → 返回 LLM 的输出,如 "Positive"

  3. 最终 result = "Positive"

✅ 输入是 dict,中间变成 str,输出还是 str ------ LangChain 自动处理类型转换(前提是组件兼容)。


📦 四、扩展:多级链式调用

你可以继续拼接更多组件:

python 复制代码
from langchain_core.output_parsers import StrOutputParser

chain = (
    prompt 
    | llm 
    | StrOutputParser()  # 把 LLM 的 AIMessage 转为纯字符串
)

result = chain.invoke({"text": "Thank you"})  # 直接得到 str,无需 .content

这相当于:

python 复制代码
prompt_str = prompt.format(**{"text": "Thank you"})
ai_msg = llm.invoke(prompt_str)
result = StrOutputParser().invoke(ai_msg)

但链式写法更清晰、模块化、可测试。


🧪 五、自己实现一个简易版(理解原理)

python 复制代码
class MyRunnable:
    def __or__(self, other):
        return MyChain(self, other)
    
    def invoke(self, x):
        raise NotImplementedError

class PromptTemplate(MyRunnable):
    def invoke(self, inputs):
        return f"Input: {inputs['text']}"

class DummyLLM(MyRunnable):
    def invoke(self, prompt):
        return f"Response to '{prompt}'"

class MyChain(MyRunnable):
    def __init__(self, first, second):
        self.first = first
        self.second = second
    
    def invoke(self, x):
        return self.second.invoke(self.first.invoke(x))

# 使用
chain = PromptTemplate() | DummyLLM()
print(chain.invoke({"text": "Hello"}))
# 输出: Response to 'Input: Hello'

这就是 | 链式调用的核心思想!


✅ 总结

概念 说明
链式调用 用 `
底层原理 __or__ 运算符重载 + Runnable.invoke() 协议
优势 代码简洁、可读性强、易于组合和复用
适用框架 LangChain、LlamaIndex(部分)、自定义 AI pipeline

💡 记住:a | b | c 不是"或"逻辑,而是 c(b(a(input))) 的函数组合!

这种设计灵感来源于 Unix 管道(cat file | grep word | sort),是现代 AI 工程中非常优雅的抽象方式。

相关推荐
栈与堆2 小时前
LeetCode 21 - 合并两个有序链表
java·数据结构·python·算法·leetcode·链表·rust
CCPC不拿奖不改名2 小时前
循环神经网络RNN:整数索引→稠密向量(嵌入层 / Embedding)详解
人工智能·python·rnn·深度学习·神经网络·自然语言处理·embedding
鹤入云霄2 小时前
基于Python的空气质量监测系统
python
长行4 小时前
Python|Windows 安装 DeepSpeed 安装方法及报错 Unable to pre-compile async_io 处理
windows·python·deepspeed
百锦再4 小时前
python之路并不一马平川:带你踩坑Pandas
开发语言·python·pandas·pip·requests·tools·mircro
Python之栈4 小时前
5款拖拽式Python GUI生成器助你快速打造炫酷界面
python
灏瀚星空4 小时前
基于 Python 与 GitHub,打造个人专属本地化思维导图工具全流程方案(上)
开发语言·人工智能·经验分享·笔记·python·个人开发·visual studio
用什么都重名4 小时前
「实战指南」使用 Python 调用大模型(LLM)
python·大模型·llm·api调用
是Dream呀4 小时前
Python从0到100(一百):基于Transformer的时序数据建模与实现详解
开发语言·python·transformer