一、核心模块
(一)Messages 心智模型:多轮对话的底层逻辑
LangChain 中多轮对话的本质是消息列表的持续追加,通过明确消息角色与顺序,实现上下文的有效传递与规则约束。
- 三类核心消息及其职责:
- SystemMessage(系统提示词):定义 AI 的身份、规则与输出格式,权限最高,需置于消息列表首位,全局生效。
- HumanMessage(用户消息):承载用户的提问、指令或任务描述,是模型的核心输入之一。
- AIMessage(AI 消息):模型基于前两类消息生成的回复,作为对话上下文的一部分参与后续交互。
- 关键原则:消息顺序直接影响交互效果,SystemMessage 必须优先于 HumanMessage,避免规则失效;多轮对话中,每一轮新消息都会追加到列表中,确保上下文不丢失。
代码示例:基础消息列表构建
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
# 构建基础消息列表(核心:SystemMessage 必须在首位)
messages = [
SystemMessage(content="你是一个专业的Python编程助手,回答需简洁且附带代码示例。"),
HumanMessage(content="请解释什么是列表推导式")
]
# 模拟多轮对话:追加AI回复和新的用户提问
ai_response = AIMessage(content="列表推导式是Python中创建列表的简洁方式,语法:[表达式 for 变量 in 可迭代对象 if 条件]")
messages.append(ai_response)
messages.append(HumanMessage(content="请举一个过滤偶数的例子"))
print("消息列表内容:")
for msg in messages:
print(f"[{msg.type}] {msg.content}")
输出结果:
[system] 你是一个专业的Python编程助手,回答需简洁且附带代码示例。
[human] 请解释什么是列表推导式
[ai] 列表推导式是Python中创建列表的简洁方式,语法:[表达式 for 变量 in 可迭代对象 if 条件]
[human] 请举一个过滤偶数的例子
(二)ChatPromptTemplate 变量注入:高效复用模板
变量注入的核心是分离固定规则与可变参数,通过模板化管理提升开发效率与可维护性,核心实现方式有两种:
- from_messages:通过组合 SystemMessage 和 HumanMessage 模板,嵌入可变参数占位符(如
{role}{task}),生成可复用的消息列表模板。 - from_template:基于单一字符串模板构建,适用于简单场景;多轮或多角色场景更推荐 from_messages,结构更清晰。
- 核心流程:定义模板(明确规则与占位符)→ 调用 invoke 方法注入变量 → 自动生成完整消息列表,注入时需确保变量与占位符一一对应,避免报错。
代码示例:两种模板构建方式
from langchain_core.prompts import ChatPromptTemplate
# 方式1:from_messages(推荐,多角色/多轮场景)
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一名{role},回答需符合{field}领域的专业规范,字数不超过{limit}字。"),
("human", "请解释{concept}的核心原理")
])
# 注入变量生成完整消息
messages = prompt_template.invoke({
"role": "数据分析师",
"field": "大数据",
"limit": 100,
"concept": "Hadoop"
})
print("From Messages 模板生成结果:")
print(messages)
# 方式2:from_template(简单单轮场景)
simple_template = ChatPromptTemplate.from_template(
"作为{role},请用{language}解释{concept}"
)
simple_messages = simple_template.invoke({
"role": "前端工程师",
"language": "中文",
"concept": "Vue响应式原理"
})
print("\nFrom Template 模板生成结果:")
print(simple_messages)
(三)ChatOpenAI 模型配置与运行方式
模型配置的核心是兼容不同厂商的大语言模型,遵循 OpenAI 协议实现统一调用,同时支持多样化的运行模式。
- 两种配置类型:
- 标准 OpenAI 配置:直接配置模型名称、API 密钥等参数,无需额外指定基础路径。
- 第三方服务配置(如 SiliconFlow):需通过 openai_api_base 指定第三方服务的基础路径,密钥建议存储在环境变量中,保障安全。
- 三种运行方式:
- invoke:单次同步调用,适用于单一任务的精准处理。
- batch:批量调用,可同时传入多个输入参数,高效生成批量结果。
- stream:流式调用,逐字输出结果,优化用户等待体验,适用于对话类产品。
代码示例:模型配置与三种调用方式
from langchain_openai import ChatOpenAI
import os
# 1. 模型配置(两种方式)
# 方式1:标准OpenAI配置
openai_llm = ChatOpenAI(
model="gpt-3.5-turbo",
api_key=os.getenv("OPENAI_API_KEY"), # 从环境变量读取密钥,避免硬编码
temperature=0.3 # 低随机性,适合结构化输出
)
# 方式2:第三方兼容服务(如硅基流动)
silicon_llm = ChatOpenAI(
model="deepseek-chat",
api_key=os.getenv("SILICON_API_KEY"),
openai_api_base="https://api.siliconflow.cn/v1", # 第三方服务基础路径
temperature=0.7
)
# 2. 三种调用方式
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个简洁的回答助手,只输出核心答案,不超过50字。"),
("human", "{question}")
])
# 方式1:invoke(单次调用)
single_result = openai_llm.invoke(prompt.invoke({"question": "LangChain的核心价值是什么"}))
print("Invoke 单次调用结果:", single_result.content)
# 方式2:batch(批量调用)
batch_inputs = [
prompt.invoke({"question": "什么是LCEL"}),
prompt.invoke({"question": "结构化输出的作用"})
]
batch_results = openai_llm.batch(batch_inputs)
print("\nBatch 批量调用结果:")
for i, res in enumerate(batch_results):
print(f"问题{i+1}答案:", res.content)
# 方式3:stream(流式调用)
print("\nStream 流式调用结果(逐字输出):")
stream_results = openai_llm.stream(prompt.invoke({"question": "Runnable接口的作用"}))
for chunk in stream_results:
print(chunk.content, end="", flush=True)
(四)OutputParser 结构化输出:从字符串到可验证对象
结构化输出的目标是将模型的非结构化文本输出,转化为格式固定、可直接解析的对象,便于后续开发使用。
- 核心实现:通过 PydanticOutputParser 结合 Schema 定义(明确输出数据的字段、类型等),再搭配 format_instructions(格式要求说明),强制模型按指定格式输出。
- 链路串联:利用管道符将 prompt(提示词)、llm(大模型)、parser(解析器)串联为
prompt | llm | parser最小链路,直接输出可验证的结构化对象,无需手动处理字符串。
代码示例:结构化输出解析
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from langchain_core.prompts import ChatPromptTemplate
# 1. 定义结构化输出的Schema
class CodeExplanation(BaseModel):
title: str = Field(description="代码示例的标题")
code: str = Field(description="完整的代码片段")
explanation: str = Field(description="代码的核心解释,不超过100字")
# 2. 创建解析器并生成格式说明
parser = PydanticOutputParser(pydantic_object=CodeExplanation)
format_instructions = parser.get_format_instructions()
# 3. 构建包含格式要求的提示词
prompt = ChatPromptTemplate.from_messages([
("system", f"你是Python编程助手,需按指定格式输出。{format_instructions}"),
("human", "请提供一个计算斐波那契数列的Python代码示例")
])
# 4. 串联链路并执行
chain = prompt | openai_llm | parser # LCEL管道符串联
result = chain.invoke({})
# 5. 结构化结果使用
print("结构化输出结果:")
print(f"标题:{result.title}")
print(f"代码:\n{result.code}")
print(f"解释:{result.explanation}")
# 验证结果类型(可直接作为对象使用)
print(f"\n结果类型:{type(result)}")
print(f"代码字段类型:{type(result.code)}")
(五)Runnable 统一接口与 LCEL 管道符
- Runnable 是 LangChain 中所有核心组件的统一接口,确保提示词模板、模型、解析器等组件都支持 invoke、batch、stream 三种调用方式,降低组件组合成本。
- LCEL(LangChain Expression Language)的核心是通过管道符
|,将复杂的调用流程简化为直观的数据流表达式,相较于逐步调用更简洁、更工程化。
代码示例:LCEL 管道符串联完整链路
# 完整链路:提示词模板 → 模型 → 解析器
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# 1. 定义组件
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个幽默的科普助手,用一句话解释概念。"),
("human", "请解释{concept}")
])
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.8)
parser = StrOutputParser() # 基础字符串解析器
# 2. LCEL管道符串联(核心:数据从左到右流转)
chain = prompt | llm | parser
# 3. 执行链路
result = chain.invoke({"concept": "人工智能"})
print("完整链路执行结果:", result)
# 批量执行
batch_results = chain.batch([{"concept": "机器学习"}, {"concept": "深度学习"}])
print("\n批量执行结果:")
for res in batch_results:
print("-", res)
(六)并行与透传:优化复杂任务处理流程
针对多任务协作场景,LangChain 提供了并行执行与输入透传两种核心能力,提升任务处理效率。
- RunnablePassthrough:实现输入的原样透传,可在不修改原始输入的前提下,将其传递至后续组件,适用于需要保留原始信息的场景。
- RunnableParallel:支持同时运行多条独立子链,并行处理多个任务,无需等待单个任务完成,适用于无依赖关系的多任务场景,大幅提升处理速度。
代码示例:并行执行与输入透传
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
# 1. 定义基础组件
prompt_summary = ChatPromptTemplate.from_messages([
("system", "请总结以下文本的核心内容,不超过50字。"),
("human", "{text}")
])
prompt_keywords = ChatPromptTemplate.from_messages([
("system", "请提取以下文本的3个核心关键词,用逗号分隔。"),
("human", "{text}")
])
summary_chain = prompt_summary | openai_llm | StrOutputParser()
keywords_chain = prompt_keywords | openai_llm | StrOutputParser()
# 2. 并行执行多任务
parallel_chain = RunnableParallel({
"原始文本": RunnablePassthrough(), # 透传原始输入
"摘要": summary_chain,
"关键词": keywords_chain
})
# 3. 执行并行链路
input_text = "LangChain是一个用于构建大语言模型应用的框架,提供了模块化的组件和灵活的链路编排能力,简化了AI应用的开发流程。"
result = parallel_chain.invoke({"text": input_text})
print("并行执行结果:")
print(f"原始文本:{result['原始文本']['text']}")
print(f"摘要:{result['摘要']}")
print(f"关键词:{result['关键词']}")
二、核心逻辑与学习总结
- LangChain 的核心设计思想是模块化 与标准化:通过拆分核心功能为独立组件(模板、模型、解析器),并基于统一的 Runnable 接口和 LCEL 管道符实现灵活组合,大幅降低大模型应用的开发门槛。
- 代码实践关键要点:
- 消息列表中 SystemMessage 必须置于首位,变量注入需保证占位符与参数一一对应;
- 模型密钥优先从环境变量读取,避免硬编码泄露;
- 结构化输出需明确 Schema 定义,结合 LCEL 管道符可简化链路开发;
- 并行执行适用于无依赖的多任务场景,透传可保留原始输入信息。
- 应用场景延伸:从简单的单轮查询到复杂的多任务并行分析,都可基于上述核心模块快速搭建解决方案,实际开发中需根据场景选择合适的调用方式(如对话场景用流式调用、批量处理用 batch 调用)。