文章目录
-
- 前言
- 一、提示词模板:标准化管理你的Prompt,告别字符串拼接硬编码
-
- [1.1 原生字符串拼接的致命缺陷](#1.1 原生字符串拼接的致命缺陷)
- [1.2 四大核心模板全场景详解](#1.2 四大核心模板全场景详解)
-
- [1. PromptTemplate 单轮文本基础模板](#1. PromptTemplate 单轮文本基础模板)
-
- 基础实例
- [局部固定变量 partial 局部填充](#局部固定变量 partial 局部填充)
- [2. ChatPromptTemplate 对话角色模板(开发首选)](#2. ChatPromptTemplate 对话角色模板(开发首选))
- [3. MessagesPlaceholder 对话历史占位插槽](#3. MessagesPlaceholder 对话历史占位插槽)
- [4. FewShotPromptTemplate 少样本示例模板](#4. FewShotPromptTemplate 少样本示例模板)
- [1.3 工业级Prompt编写规范拓展](#1.3 工业级Prompt编写规范拓展)
- 二、输出解析器:统一格式化模型返回数据,打通业务代码
-
- [2.1 解析器核心价值](#2.1 解析器核心价值)
- [2.2 四类解析器完整对比+补充拓展知识点](#2.2 四类解析器完整对比+补充拓展知识点)
-
- [1. StrOutputParser 基础文本解析器](#1. StrOutputParser 基础文本解析器)
- [2. JsonOutputParser 提示词驱动JSON解析](#2. JsonOutputParser 提示词驱动JSON解析)
- [3. llm.with_structured_output 厂商原生结构化输出【生产首选】](#3. llm.with_structured_output 厂商原生结构化输出【生产首选】)
- [4. PydanticOutputParser 带强数据校验解析器](#4. PydanticOutputParser 带强数据校验解析器)
- [2.3 解析器选型决策表(扩充细节)](#2.3 解析器选型决策表(扩充细节))
- 三、LCEL链式调用:Runnable流水线,搭积木式构建AI应用
-
- [3.1 什么是Chain & LCEL](#3.1 什么是Chain & LCEL)
- [3.2 LCEL四大核心组合器,覆盖全部复杂业务逻辑](#3.2 LCEL四大核心组合器,覆盖全部复杂业务逻辑)
-
- [1. RunnableSequence 顺序流水线(管道符|底层实现)](#1. RunnableSequence 顺序流水线(管道符|底层实现))
- [2. RunnableParallel 并行分支执行](#2. RunnableParallel 并行分支执行)
- [3. RunnablePassthrough 输入透传](#3. RunnablePassthrough 输入透传)
- [4. RunnableLambda 自定义函数注入链路](#4. RunnableLambda 自定义函数注入链路)
- [3.3 进阶生产级拓展功能](#3.3 进阶生产级拓展功能)
-
- [3.3.1 会话记忆链 RunnableWithMessageHistory](#3.3.1 会话记忆链 RunnableWithMessageHistory)
- [3.3.2 自动重试 with_retry](#3.3.2 自动重试 with_retry)
- [3.3.3 故障降级 with_fallbacks](#3.3.3 故障降级 with_fallbacks)
- [3.3.4 流式输出 stream()](#3.3.4 流式输出 stream())
- [3.3.5 异步调用 ainvoke](#3.3.5 异步调用 ainvoke)
- 四、完整端到端综合实战Demo
- 五、全文知识总结
-
- [1. 标准AI应用通用流水线](#1. 标准AI应用通用流水线)
- [2. 核心组件速查清单](#2. 核心组件速查清单)
前言
做AI应用绕不开LangChain,很多新手入门时只会简单调用llm.invoke(),一旦遇到多变量提示词、结构化数据返回、多步骤业务流程就束手无策。
本文从零拆解LangChain三大核心基石:提示词模板、输出解析器、LCEL链式调用,覆盖基础语法、实战场景、选型对比、生产级优化方案,全部配套可直接运行代码。读完你就能搭建标准化、可复用、易维护的AI流水线,告别零散、混乱的模型调用代码。
一、提示词模板:标准化管理你的Prompt,告别字符串拼接硬编码
1.1 原生字符串拼接的致命缺陷
直接使用f-string拼接提示词是新手最常踩坑的写法,仅适合极简单的单变量场景:
python
# 不推荐:硬编码拼接,扩展性极差
style = "专业学术风"
topic = "大模型上下文窗口"
prompt = f"请用{style}讲解{topic},控制在200字以内"
痛点总结:
- 多变量时代码冗长,可读性差;
- 提示词文本与业务代码耦合,修改话术需要改动业务逻辑;
- 无法复用固定指令、角色设定;
- 不支持对话历史、少样本示例等复杂场景。
提示词模板核心设计思路:框架与变量解耦,提前定义固定话术模板,运行时动态填充变量,统一管理全项目所有Prompt。
1.2 四大核心模板全场景详解
1. PromptTemplate 单轮文本基础模板
仅适用于单次无角色区分纯文本问答,底层基于字符串占位符{变量名}实现。
基础实例
python
from langchain_core.prompts import PromptTemplate
# 定义模板
base_template = PromptTemplate.from_template("用{tone}语气,总结{article}核心观点")
# 填充变量生成完整prompt
full_prompt = base_template.invoke({"tone": "客观中立", "article": "2026大模型轻量化技术白皮书"})
print(full_prompt.text)
局部固定变量 partial 局部填充
项目中大量场景存在全局固定参数(统一输出长度、统一要求简洁回答),使用partial预填充变量,减少重复传参:
python
# 预固定语气,后续仅需传入文章内容
fixed_tone_prompt = base_template.partial(tone="客观中立,通俗易懂")
res = fixed_tone_prompt.invoke({"article": "RAG检索增强原理"})
print(res.text)
2. ChatPromptTemplate 对话角色模板(开发首选)
适配现代大模型对话消息结构,区分system系统角色、human用户消息、ai模型历史回复,几乎所有对话类应用必用。
python
from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages([
("system", "你是资深后端工程师,回答{domain}相关问题,代码附带详细注释"),
("human", "请讲解{question}底层原理")
])
msg = chat_template.invoke({"domain": "Python异步", "question": "asyncio事件循环"})
print(msg.messages)
3. MessagesPlaceholder 对话历史占位插槽
实现多轮聊天记忆核心组件,在消息列表中预留位置,运行时动态插入历史对话消息,适配聊天机器人、连续问答场景。
python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
chat_with_history = ChatPromptTemplate.from_messages([
("system", "记住用户所有对话信息,不能遗忘历史内容"),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{user_input}")
])
# 传入历史对话
messages = chat_with_history.invoke({
"chat_history": [
HumanMessage("我的爱好是爬山"),
AIMessage("爬山是很棒的户外运动!")
],
"user_input": "我有什么爱好?"
})
简写技巧:无需导入类,直接使用("placeholder", "chat_history")实现同等效果。
4. FewShotPromptTemplate 少样本示例模板
单纯文字指令很难约束模型输出格式,少样本模板自动将标准示例注入Prompt,大幅提升输出一致性,适合分类、抽取、格式化生成场景。
新增补充知识点:示例选择器ExampleSelector
当示例数量庞大(几十上百条),全部塞进提示词会占用大量上下文,可使用SemanticSimilarityExampleSelector基于向量相似度筛选和问题最匹配的少量示例,降低token消耗。
python
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
# 标准示例
examples = [
{"text": "今天天气很好", "label": "正向"},
{"text": "今天下雨心情很差", "label": "负向"}
]
# 单条示例渲染模板
example_format = PromptTemplate(template="文本:{text}\n情感标签:{label}", input_variables=["text", "label"])
# 组装少样本模板
few_shot = FewShotPromptTemplate(
examples=examples,
example_prompt=example_format,
prefix="情感分类任务示例:",
suffix="文本:{input_text}\n情感标签:",
input_variables=["input_text"]
)
print(few_shot.invoke({"input_text": "今天吃到了好吃的火锅"}).text)
1.3 工业级Prompt编写规范拓展
- 边界约束量化:明确字数、格式、禁止内容,例:回答不超过150字、禁止出现专业晦涩术语、不编造不存在数据;
- 角色分层设计:system消息固定身份与全局规则,用户消息仅传入业务输入,分离职责;
- 提示词分层存储:大型项目将所有模板存入yaml/json配置文件,代码动态读取,无需硬编码;
- 分段拆分长Prompt:超长指令换行分段,模型更容易识别指令要求。
二、输出解析器:统一格式化模型返回数据,打通业务代码
2.1 解析器核心价值
大模型原生返回AIMessage对象,内容是自由自然语言文本,无法直接给前端、数据库、接口使用。输出解析器标准化处理返回结果:
- 基础场景:提取纯文本字符串;
- 业务场景:自动解析JSON、校验数据类型、生成结构化实体对象;
- 生产场景:依靠模型原生能力强制规范输出,消除乱格式问题。
2.2 四类解析器完整对比+补充拓展知识点
1. StrOutputParser 基础文本解析器
全项目使用频率最高的解析器,唯一功能:提取AIMessage中的content文本,是基础问答链标配末端组件。
python
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
# 输入AIMessage对象,输出纯字符串
text = parser.invoke(llm_response)
2. JsonOutputParser 提示词驱动JSON解析
通过在系统提示词注入JSON格式说明,引导模型输出标准JSON字符串,再自动转为Python字典。
缺陷补充:依赖模型理解能力,轻量小模型容易输出多余注释、markdown代码块、残缺JSON,生产环境不建议单独使用,适合快速原型验证。
3. llm.with_structured_output 厂商原生结构化输出【生产首选】
OpenAI、智谱、通义千问等主流大模型API内置Function Calling/结构化输出能力,在模型层面强制约束返回格式,不输出多余文字,解析零失败。
拓展知识点:支持多模型无缝切换,更换LLM无需修改解析逻辑;支持数组、嵌套Pydantic复杂结构。
python
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 嵌套复杂结构示例
class BookTag(BaseModel):
tag_name: str
weight: int = Field(description="标签权重1-10")
class BookInfo(BaseModel):
name: str
author: str
tags: list[BookTag]
# 绑定结构化输出
structured_llm = llm.with_structured_output(BookInfo)
res = structured_llm.invoke("介绍《百年孤独》")
print(res.tags[0].tag_name)
4. PydanticOutputParser 带强数据校验解析器
基于Pydantic模型完成解析+双重校验,支持自定义字段校验器、数值范围、字符串长度限制,不符合规则直接抛出异常,适合数据强规范业务(评分、表单抽取)。
补充拓展:可自定义异常捕获逻辑,当模型输出不符合规范时自动重试调用模型。
2.3 解析器选型决策表(扩充细节)
| 使用场景 | 推荐组件 | 优势 | 短板 |
|---|---|---|---|
| 普通文案生成、对话问答 | StrOutputParser | 轻量无损耗,性能最优 | 无法结构化数据 |
| 原型开发、开源小模型兼容 | JsonOutputParser | 不依赖厂商特有能力,通用性强 | 格式不稳定,易解析失败 |
| 线上生产结构化接口 | with_structured_output | API层强制格式,100%解析成功 | 仅支持主流商用大模型 |
| 数据抽取、表单、打分系统 | PydanticOutputParser | 内置数据校验,自动拦截脏数据 | 代码量略多 |
| 自定义特殊格式(XML/CSV) | 继承BaseOutputParser自定义 | 完全自由定制 | 需要手动实现解析逻辑 |
三、LCEL链式调用:Runnable流水线,搭积木式构建AI应用
3.1 什么是Chain & LCEL
LangChain 旧版本使用Chain类硬编码流水线,代码臃肿、扩展性差;新版本推荐LCEL(LangChain Expression Language) ,依靠管道符|串联所有Runnable组件。
核心前提:模板、LLM、解析器、自定义函数全部实现Runnable统一接口,共享invoke/batch/stream/ainvoke同步/异步/流式方法。
无链式 vs LCEL链式对比:
python
# 繁琐手动分步调用
prompt_val = prompt.invoke(input_dict)
msg = llm.invoke(prompt_val)
result = parser.invoke(msg)
# LCEL一行流水线
chain = prompt | llm | parser
result = chain.invoke(input_dict)
3.2 LCEL四大核心组合器,覆盖全部复杂业务逻辑
1. RunnableSequence 顺序流水线(管道符|底层实现)
组件按顺序执行,上一个组件输出作为下一个组件输入,最基础流水线。支持链式无限拼接,组合后的Chain自身仍是Runnable,可二次拼接。
2. RunnableParallel 并行分支执行
同一输入分发到多条子链并行运行,汇总所有分支输出为字典,大幅提升多维度生成效率。
拓展实战场景:文章同时生成标题、摘要、关键词,并行执行后汇总整合;
python
from langchain_core.runnables import RunnableLambda
# 并行多分支
parallel_chain = {
"title": PromptTemplate.from_template("给文章{text}生成3个标题") | llm | StrOutputParser(),
"summary": PromptTemplate.from_template("总结{text}100字摘要") | llm | StrOutputParser()
}
# 并行结果汇总后再送入大模型整合
full_chain = parallel_chain | ChatPromptTemplate.from_template("标题:{title}\n摘要:{summary}\n优化输出") | llm
3. RunnablePassthrough 输入透传
保留原始输入数据向下传递,常用于RAG、多参数链路,同时携带原始query和检索上下文:
python
# RAG标准模板
rag_chain = (
{
"query": RunnablePassthrough(),
"context": RunnableLambda(lambda q: retrieval.search(q))
}
| chat_prompt
| llm
| StrOutputParser()
)
4. RunnableLambda 自定义函数注入链路
将任意Python函数包装为Runnable,插入流水线实现数据清洗、字段转换、接口请求等自定义逻辑,打通AI与业务代码。
3.3 进阶生产级拓展功能
3.3.1 会话记忆链 RunnableWithMessageHistory
基于内存/数据库存储多轮对话历史,通过session_id区分不同用户会话,开箱即用聊天记忆,支持替换Redis、数据库持久化存储历史(拓展知识点:默认InMemory仅本地测试,线上需持久化存储)。
3.3.2 自动重试 with_retry
解决网络波动、模型限流报错,自定义最大重试次数、重试间隔:
python
stable_llm = llm.with_retry(stop_after_attempt=3, wait_between_attempts=1)
chain = prompt | stable_llm | parser
3.3.3 故障降级 with_fallbacks
主模型服务不可用时自动切换备用模型,保障服务可用性,线上高可用必备:
python
main_llm = ChatOpenAI(model="gpt-4o")
backup_llm = ChatOpenAI(model="gpt-4o-mini")
safe_llm = main_llm.with_fallbacks([backup_llm])
3.3.4 流式输出 stream()
所有LCEL链原生支持流式返回,实现打字机实时输出效果:
python
chain = prompt | llm | StrOutputParser()
for chunk in chain.stream({"concept": "向量数据库"}):
print(chunk, end="")
3.3.5 异步调用 ainvoke
高并发场景使用异步接口,提升服务吞吐量,适配FastAPI后端:
python
import asyncio
async def run_async():
res = await chain.ainvoke({"concept": "RAG"})
print(res)
asyncio.run(run_async())
四、完整端到端综合实战Demo
整合提示词模板、结构化输出、LCEL链式并行调用,实现文章情感分析+标签抽取一体化链路:
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnableParallel
from pydantic import BaseModel, Field
# 1. 定义结构化输出模型
class ArticleAnalysis(BaseModel):
sentiment: str = Field(description="情感:正向/负向/中性")
score: int = Field(ge=1, le=10, description="情感分数1-10")
keywords: list[str]
# 2. 初始化模型与模板
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
structured_llm = llm.with_structured_output(ArticleAnalysis)
summary_prompt = ChatPromptTemplate.from_template("精简总结下文:{article}") | llm | StrOutputParser()
# 3. LCEL并行链:同时做结构化抽取+文本总结
full_workflow = RunnableParallel({
"analysis": ChatPromptTemplate.from_template("分析文章{article}") | structured_llm,
"summary": summary_prompt
})
# 4. 执行完整流水线
result = full_workflow.invoke({"article": "国产大模型落地速度持续加快,各类轻量化方案大幅降低部署成本"})
print("情感分析:", result["analysis"])
print("文章总结:", result["summary"])
五、全文知识总结
1. 标准AI应用通用流水线
用户输入 → 提示词模板(格式化、注入示例/对话历史) → 大模型调用 → 输出解析器(文本/结构化对象) → 业务可用结果
全流程使用LCEL管道符串联,复杂分支逻辑依靠四大Runnable组合器实现。
2. 核心组件速查清单
- 提示词模板
- PromptTemplate:单轮纯文本
- ChatPromptTemplate:角色对话(主流)
- MessagesPlaceholder:对话历史插槽
- FewShotPromptTemplate:少样本示例约束输出
- 输出解析器
- StrOutputParser:提取纯文本
- with_structured_output:生产环境结构化首选
- PydanticOutputParser:带数据校验抽取
- LCEL组合工具
|顺序执行、RunnableParallel并行、RunnablePassthrough透传、RunnableLambda自定义函数- 拓展能力:记忆会话、自动重试、故障降级、流式/异步调用