【LangChan 0.3 组件使用 - 超详细版】(持续更新)
文章目录
一、组件简述
- LLM 大语言模型
- 配置大模型(模型名称、API密钥、参数等)
- 通用格式兼容 OpenAI 标准
- 也支持单独导入各厂商的包,例如通义千问(TongYi)
- 解析器
- 将大模型返回的结果转换成指定的格式。
- 支持三种解析器类型:JSON、List、对象
- 提示词模板
- 两种:PromptTemplate、ChatPromptTemplate
- LCEL 链式
- 链就是将多个步骤连接起来,按照顺序一步步执行。管道式符号 | 创建链;组件间数据类型自动转换、异步调用、支持流式输出、错误处理、重试、缓存、支持自定义。
- 案例:
- chain = prompt 提示词 | llm 对话模型 | parser 解析器
result = chain.invoke({“city”:“北京”, “region”:“朝阳”}) # 填充提示词模板内容,返回AI回答。
- chain = prompt 提示词 | llm 对话模型 | parser 解析器
- 原理
- 当使用 | 符号,实际上调用的是对象的魔术方法 _or_:
- a | b 时,Python实际执行:
- result = a._or_(b)
二、组件描述 & 案例
1. langchain 安装
------ langchain 库 ------
pip install langchain
-------- 其他库 ----------
# LangGraph
pip install -U langgraph
# dotenv管理密钥,加载环境变量等【Python库】
pip install python-dotenv
# 千问
pip install -U langchain-community dashscope
# DeepSeek
pip install langchain-deepseek
# 外部资源集成
!pip install langchain_community
# 直接转换为 REST API
pip install "langserve[all]"
# 观测平台
pip install -U langsmith
2. LLM 大模型模型
langchain语言模型主要分为两种写法:
- LLM 通用模型:输入字符串,输出字符串。
- ChatModel 对话模型【常用】:输入BaseMessage对象,输出是 AIMessage 对象,但使用时通常取其 content 属性获取文本。
2.1. LLM 模型(旧式)
# LLM.invoke
from langchain_community.llms.tongyi import Tongyi
llm = Tongyi()
print(llm.invoke("你好"))
# 输出:你好呀!✨ 很高兴见到你!
2.2. ChatModel 对话模型【常用】
OpenAI 兼容各家大模型。
from langchain_openai import ChatOpenAI
# import os
# os.environ["OPENAI_API_KEY"] = "your-api-key" # 替换为实际密钥
# 初始化模型
llm = ChatOpenAI(
model="qwen3.6-plus",
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key="sk-xxx",
max_tokens=500
)
# 调用
response = llm.invoke("你好")
print(response.content)
# 输出:content='你好!很高兴见到你,有什么可以帮你的吗?😊' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 5, 'total_tokens': 19, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 5}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_08f168e49b_prod0820_fp8_kvcache', 'id': 'b091f984-a197-42cb-94d1-80bfc1bb8631', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--924ee09c-7aac-4ee1-b148-613099d36b53-0' usage_metadata={'input_tokens': 5, 'output_tokens': 14, 'total_tokens': 19, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
2.3. 自定义大模型接口(使用私有化部署的 vLLM 大模型)
很完整的封装案例可用于生产(生产环境可以再加些日志、监控…)
该案例langchain版本可能有问题,使用时注意下。
week04\p12-自定义大模型接口
3. 提示词模板
提示词模板是用于生成提示词的模板。例如,{name},你好!我是你的朋友小爱同学。就是一个提示词模板。
提示词模板中可以使用变量,变量名由字母、数字和下划线组成,且必须以字母开头。
3.1. PromptTemplate 提示词模板
- 第一种用法
推荐用(简便)
from langchain_core.prompts import PromptTemplate
# 定义模板
prompt = PromptTemplate.from_template(
"你好{name},\n 你要查询{city}的景点吗?"
)
# 添加参数
result = prompt.format(name="王明", city="北京")
print(result)
# 输出:你好王明,你要查询北京的景点吗?
- 第二种用法
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=["topic", "audience", "tone"], # 显示定义变量
template="""
请为{audience}写一篇关于{topic}的文章。
写作风格应该是{tone}的。
文章要求:
- 内容准确且有用
- 结构清晰
- 适合目标受众
"""
)
formatted_prompt = prompt.format(
topic="人工智能",
audience="初学者",
tone="通俗易懂"
)
print(formatted_prompt)
3.2. ChatPromptTemplate 对话模板
# 使用 ChatPromptTemplate 创建对话模板
from langchain_core.prompts import ChatPromptTemplate
# 创建包含 system 和 human 消息的聊天模板
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个名为 {ai_name} 的有用 AI 助手。"),
("human", "你好,我的名字是 {name}。{issue}")
])
# 格式化消息
messages = chat_prompt.format_messages(
ai_name="AI助理",
name="王明",
issue="今天天气怎么样?"
)
for message in messages:
print(f"{message.type}: {message.content}")
# 输出:
# system: 你是一个名为 AI助理 的有用 AI 助手。
# human: 你好,我的名字是 王明。今天天气怎么样?
3.3. 自定义模板
有复杂提示词参数时使用
week04\p11-自定义模板.ipynb
4. 输出解析器
输出解析器是 LangChain 中的重要组件,用于将大语言模型(LLM)的原始文本输出转换为结构化数据格式,便于程序进一步处理和使用。
主要功能
- 格式化输出: 将 LLM 的自然语言输出解析为 JSON、XML、列表等结构化格式
- 类型转换: 将文本数据转换为 Python 对象(字典、列表、自定义类等)
- 数据验证: 确保输出符合预期的格式和约束条件
- 错误处理: 处理解析失败的情况,提供重试机制
以下为常见的输出解析器类型案例:
StructuredOutputParser = JSON字典解析器CommaSeparatedListOutputParser = LIst 列表解析器PydanticOutputParser = 对象解析器
解析器的创建流程:定义响应数据结构 -> 创建解析器 -> 获取格式指令 -> 嵌入提示词模板
4.1. JSON 格式解析器 StructuredOutputParser
例如希望大模型返回这样的 JSON 格式数据:
{
“answer”: “巴黎”,
“source”: “地理知识”
}
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.prompts import PromptTemplate
from langchain_community.llms.tongyi import Tongyi
# 第1步. 定义响应数据结构【明确指定模型返回的JSON数据结构及参数说明】
response_schemas = [
# 参数说明:name:JSON中的key(字段名), description:告诉 LLM 这个字段应该包含什么内容(作为提示的一部分)
ResponseSchema(name="answer", description="问题的答案"),
ResponseSchema(name="source", description="答案来源")
]
# 第2步. 创建解析器(StructuredOutputParser - 结构化输出解析器)
parser = StructuredOutputParser.from_response_schemas(response_schemas)
# 第3步. 获取格式指令:生成一段文本,告诉大模型应该以什么JSON格式返回数据
# 这段文本会被嵌入到提示词中,指导大模型按我们定义的结构输出
format_instructions = parser.get_format_instructions()
# 第4步. 在 prompt 中使用(将解析器的格式嵌入到提示词模板中)
prompt = PromptTemplate(
template="回答问题:{question}\n\n{format_instructions}", # {format_instructions} 是占位符
input_variables=["question"], # 声明:question 是运行时需要传入的变量
partial_variables={"format_instructions": format_instructions} # 预填充:将解析器的格式指令绑定到 {format_instructions} 占位符
)
# 初始化大模型【千问大模型,环境变量需要指定 DASHSCOPE_API_KEY=你的API-KEY】
llm = Tongyi(temperature=0)
# 创建链 chain
chain = prompt | llm | parser
# 调用
result = chain.invoke({"question": question})
# 取数据
print(f"问题的答案:{result['answer']}")
print(f"答案来源:{result['source']}")
4.2. List 列表解析器 CommaSeparatedListOutputParser
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
# 第1步. 创建列表解析器(不需要定义结构!)
parser = CommaSeparatedListOutputParser()
# 第2步. 获取格式指令
format_instructions = parser.get_format_instructions()
# 第3步. 创建提示词模板
prompt = PromptTemplate(
template="列出{subject}的3个要点:\n\n{format_instructions}",
input_variables=["subject"],
partial_variables={"format_instructions": format_instructions}
)
# ... 最后大模型返回的就是List列表
3.3. 对象解析器 PydanticOutputParser
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
# 1. 定义结构(Pydantic模型)
class PersonInfo(BaseModel):
name: str = Field(description="人物姓名")
age: int = Field(description="年龄")
occupation: str = Field(description="职业")
# 2. 创建解析器
parser = PydanticOutputParser(pydantic_object=PersonInfo)
# 3. 获取格式指令
format_instructions = parser.get_format_instructions()
# 4. 创建提示词模板
prompt = PromptTemplate(
template="生成一个虚构人物\n\n{format_instructions}",
input_variables=[],
partial_variables={"format_instructions": format_instructions}
)
# 5. 调用大模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
chain = prompt | llm | parser
# 6. 获取结果
result = chain.invoke({})
print(result)
print(f"姓名:{result.name},年龄:{result.age},职业:{result.occupation}")
3.4. 自定义输出解析器
将大模型返回的结果封装成指定格式。
week04\p13-自定义输出解释器.ipynb
5. LLM 参数设置 & 添加标签(用于日志追踪)
- LLM 参数设置:同一个模型实例在不同场景使用时,配置不同参数。
tags 标题:添加日志方便追踪。
# 给 chain 设置模型参数
# 同一个模型实例在不同场景使用时,配置不同参数
chain = prompt | llm | parser
chain = chain.bind(temperature=0.3, max_tokens=512)
-----
# 添加标签用于日志追踪
# LangChain 官方推荐的日志 / 追踪方式
chain = prompt | llm | parser
chain = chain.with_tags(["RAG服务", "线上环境", "v2.5"]) # 加标签,日志输出
result = chain.invoke({"question": "你好"})
-----
# 添加元数据(尽量不动元数据)
chain = chain.with_metadata({"version": "1.0", "author":"team"})
6. invoke同步、ainvoke异步、batch批量异步调用大模型
注:这里所有的 await(包括 async for、async with)都会挂起当前函数,等执行完成后才会往下执行(不会出现异步还没执行完,但是函数执行结束的情况)。
- invoke() :同步执行大模型,执行完成后一次性返回完整结果。
- ainvoke():异步执行大模型,执行完成后一次性返回完整结果。
- batch():批量异步执行
多个问题让一个大模型回答 - stream():同步流式调用。
- astream():异步流式调用。
week04\p14-链的解析.ipynb
# 伪代码...
# 构建链
chain = prompt | llm | parser
# ========== 基础调用 ==========
# 同步调用 - 阻塞当前线程
result = chain.invoke({"city":"北京", "region":"朝阳"})
# 异步调用 - 挂起当前协程,不阻塞事件循环
# 注:await 会挂起当前函数,等待执行完成后才会往下执行,但不会阻塞事件循环
result = await chain.ainvoke({"city":"北京", "region":"朝阳"})
# ========== 批量调用 ==========
# 同步批量 - 阻塞当前线程(内部用线程池实现并发)
# 注:会阻塞主线程,但任务之间是并发的
results = chain.batch([input1, input2, input3])
# 异步批量 - 不阻塞事件循环,并发执行
# 注:挂起当前函数,等待所有任务完成才会往下执行,但等待期间可执行其他协程
results = await chain.abatch([input1, input2, input3])
# ========== 流式调用 ==========
# 同步流式 - 阻塞当前线程,边生成边输出
for chunk in chain.stream({"city": "北京", "region": "朝阳"}):
print(chunk, end="", flush=True)
# 异步流式 - 不阻塞事件循环,边生成边输出
# 注:挂起当前函数,等待所有任务完成才会往下执行,但等待期间可执行其他协程
async for chunk in chain.astream({"city": "上海", "region": "浦东"}):
print(chunk, end="", flush=True)
7. 上下文记忆(短记忆、Mem0长记忆)
LangChain 上下文记忆系统 - 短时记忆、Mem0长期记忆增强框架
8. 工具调用(普通模式、ReAct思维链+行动)
8.1. Agent 使用工具调用
8.2. LangChain 内置工具
LangChain内置了很多好用的工具(搜索引擎、数据库操作、代码解释器等)【点击跳转查看内置工具文档】
以下是使用搜索工具 DuckDuckgoSearch 的案例:
# 安装搜索工具 duckduckgo-search
!pip install -qU duckduckgo-search langchain-community ddgs
# 基本搜索方式,返回 String 文本
from langchain_community.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun() # 基本模式
search.invoke("苹果公司的创始人 ?") # 执行搜索
# 输出:'2025年7月22日 — 1976年4月,史蒂夫·賈伯斯、史蒂夫·沃茲....
# 获取更多附加信息(例如链接、来源),返回 JSON 格式
from langchain_community.tools import DuckDuckGoSearchResults
search = DuckDuckGoSearchResults(output_format="list") # 溯源模式
search.invoke("苹果公司的创始人 ?") # 执行搜索
# 输出
[{'snippet': '2025年7月22日 — 1976年4月,史蒂夫·賈伯斯、史蒂夫·沃茲尼亞克和羅納德·韋恩創立了蘋果公司,目的是為了研發和銷售沃茲尼亞克Apple I個人電腦,但韋恩12天後就放棄了自己的股份。',
'title': '蘋果公司- 維基百科,自由的百科全書',
'link': 'https://zh.wikipedia.org/zh-hk/蘋果公司'},
{'snippet': '2025年7月13日 — 1976年,沃茲尼克與史蒂夫·賈伯斯合夥創立蘋果電腦公司,並在1970年代末研發出第一代和第二代蘋果電腦。 二代電腦一經發售即風靡全美,成為1970-80年代之交銷量最佳的個人電 ...',
'title': '史蒂夫·沃茲尼克',
'link': 'https://zh.wikipedia.org/zh-hk/史蒂夫·沃兹尼亚克'}]
9. 普通方法附加重试能力(Runnable 套壳)
# 普通方法
def query_order(order_id: str) -> dict:
# 查数据库、调 API 等
return {"order_id": order_id, "status": "ok"}
runner = RunnableLambda(query_order).with_retry() # 套壳 + 抛异常时重试,默认共 3 次
result = runner.invoke("20251114001") # 传入参数,并执行方法
三、链的常用处理(类型定义[AOP增强]、并行跑多个大模型、错误处理、动态配置大模型参数)
1. 类型定义 - 类似AOP上下文增强
常用用途:清洗用户输入数据、封装大模型返回结果。
# 明确类型定义(输入什么类型、输出什么类型)
## 输入:一个字典 {"key": "字符串"}
## 输出:一个字典 {"key": 任意类型}
class MyChain(Runnable[Dict[str, str], Dict[str, Any]]):
pass
# 完整案例
from typing import Dict, Any, Optional
from langchain_core.runnables import Runnable, RunnableConfig
# 1. 定义类型安全的链(接收 dict 输入,输出 dict)
class MyChain(Runnable[Dict[str, str], Dict[str, Any]]):
"""一个简单的自定义链:提取输入中的 name 字段,返回问候语"""
# 核心参数
# - input 用户输入。
# - config 接收回调、标签、元数据等运行时配置
def invoke(self, input: Dict[str, str], config: Optional[RunnableConfig] = None, **kwargs: Any) -> Dict[str, Any]:
# 从输入字典中获取 name,如果没有则使用默认值
name = input.get("name", "访客")
# 处理业务逻辑
greeting = f"你好,{name}! 欢迎使用langchain."
# 返回字典格式的输出
return {
"greeting": greeting, # 你好,王明! 欢迎使用langchain.
"input_name": name, # 王明
"status": "success"
}
# 2. 使用方式一:直接调用
chain = MyChain()
result = chain.invoke({"name": "王明"})
print(result)
# 输出: {'greeting': '你好,王明! 欢迎使用langchain.', 'input_name': '王明', 'status': 'success'}
# 3. 使用方式二:通过 LCEL 管道与其他组件串联
from langchain_core.runnables import RunnableLambda
# 先做预处理:提取用户输入
preprocess = RunnableLambda(lambda x: {"name": x["user_input"].upper()})
# 管道组合:预处理 -> 自定义链
pipeline = preprocess | chain
# 执行整个管道
final_result = pipeline.invoke({"user_input": "bob"})
print(final_result)
# 输出: {'greeting': 'Hello, BOB! Welcome to LangChain.', 'input_name': 'BOB', 'status': 'success'}
# 4. 批量处理(自动支持)
batch_results = chain.batch([
{"name": "Alice"},
{"name": "Bob"},
{"name": "Charlie"}
])
print(batch_results)
# 输出: 三个结果的列表
2. 并行跑多个大模型【一个问题让多个大模型回答】
调用 .invoke() 后会等所有大模型都跑完后主线程才会往下走。
# 并行(同步跑多个大模型)
parallel_processing = RunnableParallel({
"fast_analysis": quick_model,
"detailed_analysis": detailed_model
})
# 完整案例
from langchain_core.runnables import RunnableParallel
from langchain_ollama import ChatOllama
# 两个模型
fast_model = ChatOllama(model="qwen2.5:7b")
detailed_model = ChatOllama(model="qwen2.5:14b")
# 并行执行【重点】
parallel = RunnableParallel({
"快模型回答": fast_model,
"慢模型回答": detailed_model
})
# 调用(两个模型同时跑)
result = parallel.invoke("什么是RAG?") # 等待所有并行任务都完成后,才继续往下执行。
# 取不同模型结果【重点】
print(result["快模型回答"])
print(result["慢模型回答"])
3. 错误处理(重试 | 切换备选大模型)
应用场景:
当主大模型运行异常或触发限流时,系统将自动切换至备用大模型
案例1:主模型报错时自动切换至备用大模型
案例2:主模型重试3次失败后自动切换至备用大模型
案例 1
# 添加错误处理(大模型运行错误后切换到备用大模型)
robust_chain = (
preprocessing |
model.with_fallbacks([backup_model]) | # 当大模型出现异常时,切换到备用大模型 backup_model
postprocessing
)
# 完整案例
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_models import ChatTongyi
# 设置通义千问的 API key(请替换为你的真实 key)
import os
os.environ["DASHSCOPE_API_KEY"] = "your-dashscope-api-key-here"
# 1. 主模型:qwen-turbo
main_model = ChatTongyi(
model="qwen-turbo",
temperature=0.7,
)
# 2. 备用模型:qwen-plus(更强大,作为 fallback)
backup_model = ChatTongyi(
model="qwen-plus",
temperature=0.5,
)
# 3. 后处理:解析输出
postprocessing = StrOutputParser()
# 4. 构建带 fallback 的链(使用 f-string 风格的简单提示词)
robust_chain = (
ChatPromptTemplate.from_template("{input}") # 最简单的提示词模板
| main_model.with_fallbacks([backup_model])
| postprocessing
)
# 5. 运行测试
if __name__ == "__main__":
# 正常调用
result = robust_chain.invoke({"input": "你好,请介绍一下你自己"})
print("回答:", result)
# 你也可以测试 fallback 机制(通过模拟主模型失败)
# 注意:正常情况下两个模型都可用,不会触发 fallback
案例 2
# 添加错误处理(主大模型错误重试 + 切换备用大模型)
robust_llm = llm.with_retry(
stop_after_attempt=3,
retry_if_exception_type=(RateLimitError,APIConnectionError)
).with_fallbacks([fallback_llm, local_llm]) # 两个备选大模型
# 完整案例
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_models import ChatTongyi
from openai import RateLimitError, APIConnectionError # 通义千问也使用相同的异常类型
# 设置通义千问的 API key
import os
os.environ["DASHSCOPE_API_KEY"] = "your-dashscope-api-key-here"
# 1. 主模型:qwen-turbo(重试3次)
main_model = ChatTongyi(
model="qwen-turbo",
temperature=0.7,
max_retries=0 # 关闭内置重试
).with_retry(
stop_after_attempt=3, # 重试3次
retry_if_exception_type=(RateLimitError, APIConnectionError) # 只对限流/网络错误重试
)
# 2. 备用模型:qwen-plus(作为 fallback)
backup_model = ChatTongyi(
model="qwen-plus",
temperature=0.5,
)
# 3. 后处理:解析输出
postprocessing = StrOutputParser()
# 4. 构建链:重试3次 + 备用模型
robust_chain = (
ChatPromptTemplate.from_template("{input}")
| main_model.with_fallbacks([backup_model]) # 主模型重试3次失败后,切到备用(备用可以设多个)
| postprocessing
)
# 5. 运行测试
if __name__ == "__main__":
# 正常调用
result = robust_chain.invoke({"input": "你好,请介绍一下你自己"})
print("回答:", result)
4. 大模型动态参数配置(配置管理)
动态修改大模型参数。
场景:A/B 测试、多租户应用(不同用户不同配置)、动态调整创作风格等。
# 配置管理(动态配置大模型参数)
configurable_chain = model.configurable_fields(
temperature=ConfigurableField(id="my_temperature", name="Temperature")
)
# 完整案例
from langchain_openai import ChatOpenAI
from langchain_core.runnables.config import ConfigurableField
from langchain_core.messages import HumanMessage
# 定义模型(设置默认值)
model = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0.5,
max_tokens=50
)
# 1.同时暴露两个参数可以动态调整
configurable_chain = model.configurable_fields(
# 返回值 temperature 是指"模型的 temperature 参数"
temperature=ConfigurableField(
id="my_temperature", # ← 动态修改参数时用这个
name="Temperature" # ← 命名
),
# 返回值 max_tokens 是指"模型的 max_tokens 参数"
max_tokens=ConfigurableField(
id="my_max_tokens", # ← 动态修改参数时用这个
name="Max Tokens" # ← 命名
)
)
# 2. 定义消息列表(用户问题)
messages = [HumanMessage(content="讲个笑话")]
# 3. 使用默认配置调用大模型
response_default = configurable_chain.invoke(messages)
print(f"默认 (temp=0.5, max=50): {response_default.content}\n")
# 4. 调用大模型,同时修改参数
# ⚠️ 注意:with_config 中对应 ConfigurableField 时设置的暴漏参数的 id
response_custom = (configurable_chain.with_config(configurable={
"my_temperature": 0.9,
"my_max_tokens": 100
})
.invoke(messages) # ← 消息列表
)
print(f"自定义 (temp=0.9, max=100): {response_custom.content}")
5. batch 批量调用大模型
四、将Langchain封装成网络服务 - 接口
week04\p9-封装为网络服务.ipynb
项目文件结构:
chat_service/
├── main.py # FastAPI 主应用
├── models.py # 数据模型定义
├── chat_chain.py # 对话链逻辑
├── session_manager.py # 会话管理
└── requirements.txt # 依赖包
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)