LangChain思维链与直接prompt思维链区别,一文讲清楚
思维链(CoT)是一种提示工程技术,分为单次调用和多次调用两种形式。单次调用通过Prompt引导模型在生成答案前输出推理步骤,适用于逻辑推理和数学题。多次调用则将复杂任务拆解为多个环节,通过顺序链或Agent实现,适用于需要外部工具或多步骤任务。LangChain的LCEL语法采用声明式思维,通过流水线方式定义数据流向,相比直接API调用的命令式思维更易于维护和扩展,适合复杂任务。关键区别在于工程
文章目录
一、什么是思维链(Chain of Thought)?
“思维链”(CoT)通常指的是一种提示工程(Prompt Engineering)技术,让模型在给出最终答案之前,先生成推理步骤(即“思考过程”)。
实现思维链有两种主要方式,它们的大模型调用次数不同:
-
单次调用 CoT(Prompt 层面):
- 原理: 在 Prompt 中加入 “Let’s think step by step”(让我们一步步思考)。模型会在一次生成中输出思考过程和结果。
- 调用次数: 1 次。
- 适用场景: 逻辑推理、数学题、常识问答。
-
多次调用 CoT(架构层面/Agent):
- 原理: 将复杂的任务拆解为多个环节(Chain),或者使用 Agent(智能体)。比如:步骤 1 生成大纲 -> 步骤 2 扩写内容 -> 步骤 3 翻译。
- 调用次数: 多次(每个环节调用一次)。
- 适用场景: 需要外部工具、长篇写作、多步骤复杂任务。
二、例子说明
下面我给出两个具体的 LangChain 代码例子,分别展示这两种情况。
1. 单次调用的思维链(通过 Prompt 实现)
这是最常见的 CoT 形式。即便使用了 LangChain 的 Chain 概念,它实际上只与 LLM 交互一次。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
# 初始化 LLM
llm = ChatOpenAI(model="gpt-4o")
# 定义带有思维链指令的 Prompt
# 关键在于指令: "请一步步思考 (Think step by step)"
template = """
你是一个逻辑专家。回答用户的问题。
在给出最终答案之前,请先一步步写出你的推理过程。
问题: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
# 构建 Chain (LCEL 语法)
# 这里的流程和你提供的一样
cot_chain = prompt | llm | StrOutputParser()
# 调用
question = "如果我有3个苹果,吃了一个,又买了5个,分给朋友2个,我还剩几个?"
result = cot_chain.invoke({"question": question})
print(result)
输出示例(一次生成):
推理过程:
- 开始有 3 个苹果。
- 吃掉 1 个:3 - 1 = 2 个。
- 买了 5 个:2 + 5 = 7 个。
- 分给朋友 2 个:7 - 2 = 5 个。
最终答案: 5 个。
2. 多次调用的思维链(顺序链 Sequential Chain)
如果你指的是让模型先“思考”生成一个中间结果,然后把这个结果作为输入进行下一步处理,这需要多次调用。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough
llm = ChatOpenAI(model="gpt-4o")
# --- 步骤 1: 生成大纲 (第一次调用) ---
outline_prompt = ChatPromptTemplate.from_template("请为主题 '{topic}' 写一个简短的博客大纲。")
outline_chain = outline_prompt | llm | StrOutputParser()
# --- 步骤 2: 根据大纲写文章 (第二次调用) ---
# 这里的输入来自上一步的输出
article_prompt = ChatPromptTemplate.from_template("根据以下大纲写一篇 100 字的短文:\n\n{outline}")
article_chain = article_prompt | llm | StrOutputParser()
# --- 组合链 (Sequential Chain) ---
# 这种写法不仅是思维上的链,也是执行上的链
full_chain = (
{"outline": outline_chain} # 这里执行第一个链,消耗一次 LLM 调用
| RunnablePassthrough.assign(article=article_chain) # 这里执行第二个链,消耗第二次 LLM 调用
)
# 调用
result = full_chain.invoke({"topic": "人工智能的未来"})
print("=== 大纲 (Step 1) ===")
print(result['outline'])
print("\n=== 文章 (Step 2) ===")
print(result['article'])
- 你提供的代码 (
RunnablePassthrough | prompt | llm | parser):是一个标准的单步执行单元,只调用一次大模型。 - 思维链 (CoT):通常指通过 Prompt 引导模型在一次调用中输出推理步骤。
- 多步调用:如果你需要模型“先想A,再根据A做B”,则需要构建顺序链(Sequential Chain)或使用 Agent,这时才会涉及多次调用。
三、LangChain思维链与prompt思维链区别
“工程化思维(LangChain LCEL)”与“脚本化思维(Direct API Call)”的区别。
如果单纯从大模型(LLM)的角度看,两者没有区别。无论你是用 LangChain 封装,还是直接写 Python 代码调用 OpenAI API,只要发给模型的最终字符串(Prompt)是一样的,模型的回答就是一样的。
但是,从开发者的思维和代码架构上看,差异巨大。你提供的这段 LangChain 代码体现的是一种流水线(Pipeline)思维。
下面通过对比来详细说明:
1. 核心思维对比
| 特性 | 直接调用 (Direct Prompt / API) | LangChain LCEL (chain = ...) |
|---|---|---|
| 思维模式 | 命令式 (Imperative) | 声明式 (Declarative) |
| 逻辑 | “先做A,拿到结果赋值给B,再把B传给C…” | “定义一条流水线:水从入口流过A、B、C,最后流出” |
| 关注点 | 关注每一步的执行细节和变量传递 | 关注数据流向和组件组合 |
| 修改成本 | 修改 Prompt 或模型通常需要改动多处代码 | 像积木一样替换组件(换模型、换 Prompt 只是换个变量) |
| 复杂性 | 简单任务只需几行代码,复杂任务会变成面条代码 | 简单任务显得繁琐,但极度适合复杂任务 |
2. 代码层面的直观对比
为了让你看清“思维”的不同,我们实现同一个功能:输入一个主题,让 AI 讲个笑话,并只返回笑话文本。
方式 A:直接 Prompt 思维 (脚本式)
这种方式是你自己处理所有的拼接、调用、解析。
import openai
client = openai.OpenAI(api_key="sk-...")
# 1. 准备变量
topic = "程序员"
# 2. 手动拼接 Prompt (字符串操作)
prompt_text = f"请讲一个关于{topic}的笑话。"
# 3. 发起调用 (关注具体的 API 参数)
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt_text}]
)
# 4. 手动解析结果 (需要知道 response 的深层结构)
result = response.choices[0].message.content
print(result)
- 思维特点:我要亲自控制每一步,我要知道
.choices[0].message这种细节。
方式 B:LangChain LCEL 思维 (你提供的代码)
这种方式是定义流程,不需要关心底层 API 的 JSON 结构。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough
# 1. 定义组件 (积木)
prompt = ChatPromptTemplate.from_template("请讲一个关于{topic}的笑话。")
llm = ChatOpenAI(model="gpt-4")
parser = StrOutputParser()
# 2. 定义流程 (流水线)
# 这里的 RunnablePassthrough 自动把 invoke 的参数传给 prompt
chain = (
RunnablePassthrough()
| prompt
| llm
| parser
)
# 3. 执行 (只需关注输入和输出)
result = chain.invoke({"topic": "程序员"})
print(result)
- 思维特点:我只定义数据的流向(
|),不管具体的网络请求和 JSON 解析。
3. 深入解析 RunnablePassthrough 的作用
在你提供的代码中,RunnablePassthrough() 是这一“流水线思维”的关键体现。
- 直接思维:你需要显式地写
format(topic="xxx")。 - LangChain 思维:
chain.invoke({"topic": "xxx"})传入了一个字典。RunnablePassthrough()的作用是说:“我不做处理,直接把这个输入字典透传给下一步(Prompt)”。prompt收到字典,自动匹配{topic}。
为什么要这么做?
为了组合。如果你的流程变复杂了,比如:检索数据库 -> (检索结果 + 用户问题) -> Prompt -> LLM
LangChain 可以通过 RunnablePassthrough.assign(...) 轻松地向数据流中“注入”新数据,而不需要重写整个函数。
四、总结
你给出的这段代码,其核心价值不在于“调用大模型”这件事本身,而在于它标准化了与大模型交互的接口。
- 直接 Prompt:像在手工作坊里干活,灵活但难以规模化。
- LangChain 代码:像在搭建工厂流水线,前期配置多,但一旦跑通,处理复杂任务、替换零件(模型)、增加工序(OutputParser)都非常容易。
更多推荐

所有评论(0)