这篇文章涵盖 LangChain 的核心技术点,包括:
- Prompt 模板构建(PromptTemplate / ChatPromptTemplate)
- 大模型调用(LLM)
- 输出解析(StrOutputParser / 自定义解析器)
- 链组合(Chain)
通过一个完整示例,你可以实现从基础问答到多轮智能对话的应用。
1. 完整示例:从输入到输出
下面的示例是一个 完整的 LangChain 调用大模型的流程示例,展示了从 Prompt 构建、模型调用到输出结果的整个过程。 它实现了一个简单的问答应用:用户输入问题,模型根据提示生成回答。
from langchain_core.prompts import PromptTemplate
from langchain_community.chat_models import ChatTongyi
from langchain_core.output_parsers import StrOutputParser
# 1. 初始化模型
llm = ChatTongyi(model="qwen-max", api_key="你的API_KEY")
# 2. 构造提示词
QUERY_PROMPT = PromptTemplate(
input_variables=["question"],
template='你是一个乐于助人的小助手,用户向你提问的问题是:{question}'
)
# 3. 组合链
llm_chain = QUERY_PROMPT | llm | StrOutputParser()
# 4. 执行
question = "请给我讲一个关于猫的笑话"
result = llm_chain.invoke({"question": question})
print(result)
下面我将根据这个示例,逐步讲解每个模块的作用和用法,包括:
- PromptTemplate 的构造与作用
- LLM 模型初始化与调用
- 输出解析器(OutputParser)
- 链组合(Chain)
2. 安装 LangChain
首先确保你有 Python 3.8+ 环境,然后用 pip 安装 LangChain 和常用模型 SDK:
pip install langchain langchain-core
pip install openai # 如果使用 OpenAI 模型
pip install langchain-community # 如果使用社区模型,如通义千问
3. PromptTemplate & ChatPromptTemplate
PromptTemplate 是 LangChain 对 Prompt 的抽象封装,本质上是:
一个带变量的字符串模板 + 明确的输入约束
它解决的问题是:
- 避免在代码中大量拼字符串
- 让 Prompt 结构清晰、可复用
- 明确告诉调用方:这个 Prompt 需要哪些输入
普通 PromptTemplate
from langchain_core.prompts import PromptTemplate
prompt_template = PromptTemplate(
input_variables=["question"],
template='你是一个乐于助人的小助手,用户向你提问的问题是:{question}'
)
- input_variables:模板中需要替换的变量
- template:文本模板
ChatPromptTemplate
ChatPromptTemplate 是用于 构建多角色对话的提示模板,适用于多轮对话场景。它可以将系统信息、用户输入、AI 输出和工具调用消息组合在一起,生成模型可识别的结构化对话上下文。
from langchain_core.prompts import ChatPromptTemplate
prompt_template = ChatPromptTemplate([
("system", "你是一个乐于助人的小助手"),
("user", "给我讲个关于 {topic} 的笑话")
])
prompt_template.invoke({"topic": "猫"})
| 参数 | 说明 |
|---|---|
列表 [("role", "text")] | 每条消息包含角色类型 role 和内容模板 text |
"system" | 系统提示信息,通常用于定义模型身份或行为 |
"human" 或 "user" | 用户输入,动态填充变量 |
"ai" | AI 模型输出,可用于多轮上下文记录 |
"tool" | 工具调用相关消息,用于 Agent 或多步骤任务 |
模板变量 {variable} | 消息内容中可插入的动态变量,在 invoke() 时传入 |
构造上下文示例
template = ChatPromptTemplate([
("system", "你是一个有用的人工智能机器人。你的名字是{name}。"),
("human", "你好吗?"),
("ai", "我很好,谢谢!"),
("human", "{user_input}"),
])
prompt_value = template.invoke({
"name": "Bob",
"user_input": "你叫什么名字?"
})
4. 调用大模型
在 LangChain 中,大模型(LLM)是整个链路的核心执行单元,负责根据输入的 Prompt 生成自然语言或结构化输出。 LangChain 把不同模型(OpenAI、Qwen、Claude 等)统一成一致接口:
- 可以几乎不改业务代码就切换模型
- Prompt、Parser、Chain 都可以复用
以 阿里云同义千问(Qwen)为例:
from langchain_community.chat_models import ChatTongyi
llm = ChatTongyi(model="qwen-max", api_key="你的API_KEY")
# 可以直接使用 LLM 调用
output = llm.predict("请给我讲一个关于猫的笑话")
print(output)
5. 输出解析器
在 LangChain 中,输出解析器(Output Parser)负责把大模型返回的“原始文本”转换为你需要的结构,比如json结构
from langchain_core.output_parsers import StrOutputParser
result = StrOutputParser().parse(output)
print(result)
- StrOutputParser:将模型输出格式化为字符串
- 可自定义 BaseOutputParser 解析 JSON 或清理多余文本 自定义json解析器示例:
import re
import json
from langchain_core.output_parsers import BaseOutputParser
class JsonOutputParser(BaseOutputParser[dict]): # 需要继承BaseOutputParser
"""
自定义输出解析器:
- 用于将 LLM 返回的字符串解析为 JSON
- 适用于模型输出包含 <think> 标签、Markdown 代码块等非标准 JSON 的情况
"""
def parse(self, text: str) -> dict:
"""
解析 LLM 的原始输出文本,并返回字典结构
:param text: LLM 返回的原始字符串
:return: 解析后的 dict,如果解析失败则返回空字典
"""
# 1. 移除模型输出中可能包含的 <think>...</think> 推理标签
# 一些模型(如带思维链的模型)会输出思考过程,
# 这些内容并不是合法 JSON,需要先清理
pattern = r"<think\b[^>]*>[\s\S]*?<\/think>"
text = re.sub(pattern, '', text, flags=re.IGNORECASE)
# 2. 去除 Markdown 中的 json 包裹
# 很多模型会将 JSON 包在 Markdown 代码块中,
# 这里用字符串拼接是因为博客TOC解析会有问题,正常不需要拼接
if "`" + "``json" in text:
text = text.replace("`" + "``json", "").replace("`" + "``", "").strip()
# 3. 尝试将清理后的字符串解析为 JSON
try:
json_data = json.loads(text)
return json_data
except Exception as e:
# 解析失败时记录日志,避免程序直接崩溃
log.error(f"解析 JSON 失败,原始文本: {text},错误: {e}")
return {}
6. 链组合
在 LangChain 中,Chain(链) 是一个核心概念,用于把 Prompt 模板、LLM 模型和输出解析器 组合成一个可执行的整体流程。通过 Chain,你可以把复杂的任务拆分成可复用、可组合的步骤,让模型调用更结构化和可控。
Chain的作用:
- 统一流程:把 Prompt、模型调用和输出解析组合成一个可直接调用的对象
- 复用性强:同一个 Chain 可以多次调用,减少重复代码
- 易于扩展:可以增加多步链或工具调用,实现复杂工作流
在 LangChain 中,只需要使用|就可以将多个步骤串起来,形成一个可执行的链:
llm_chain = QUERY_PROMPT | llm | StrOutputParser()
# 调用 Chain 执行
result = llm_chain.invoke({"question": "请给我讲一个关于猫的笑话"})
print(result)
如果不使用 Chain,需要手动按顺序调用每个步骤:
# 构造 Prompt
prompt_text = QUERY_PROMPT.format({"question": "请给我讲一个关于猫的笑话"})
# 调用模型
llm_output = llm.predict(prompt_text)
# 输出解析
result = StrOutputParser().parse(llm_output)
print(result)
总结
本文围绕一个最小可用的 LangChain 调用示例,系统性地介绍了 LangChain 在实际工程中最核心的几个概念与使用方式,包括:
- 如何使用 PromptTemplate / ChatPromptTemplate 构建可复用、可维护的 Prompt
- 如何通过 LangChain 统一调用大模型(LLM)
- 为什么需要 OutputParser 以及如何对模型输出进行结构化处理
- 如何使用 Chain 将多个步骤组合成清晰、可执行的流程
与直接调用模型 API 相比,LangChain 的价值并不在于“少写几行代码”,而在于让模型调用过程具备工程结构: Prompt、模型、解析逻辑各自解耦,便于复用、测试和扩展。
在此基础上,你可以很自然地继续引入对话记忆、Agent、RAG 等更复杂的能力,而不会推翻已有代码结构。