在 AI 应用开发中,你是否遇到过这些问题:
-
想要切换不同的 LLM 模型,却需要重写大量代码?
-
需要处理复杂的 Prompt 工程,但缺乏统一的模板管理?
-
想要实现 RAG(检索增强生成),但不知道如何整合向量数据库?
LangChain正是为了解决这些问题而生的开发框架。本文将带你快速入门 LangChain,掌握构建 AI 应用的核心技能。
LangChain 是什么?
- LangChain 是一套面向大模型的开发框架(SDK)
- LangChain 是 AGI 时代软件工程的一个探索和原型
- 简化了创建 LLM 应用的过程,提供了统一的接口和丰富的工具链
LangChain 的核心组件
1.功模型I/O封装
- Chat Models:对语言模型接口的封装
- PromptTemple:提示词模板
- OutputParser:解析输出
2.数据连接封装
- Document Loaders:各种格式文件的加载器
- Document Transformers:对文档的常用操作,如:split, filter, translate, extract metadata, etc
- Text Embedding Models:文本向量化表示,用于检索等操作
- Verctorstores & Retrievers:向量数据库与向量检索
3.架构封装
-
Chain/LCEL:实现一个功能或者一系列顺序功能组合
-
Agent:根据用户输入,自动规划执行步骤,自动选择每步需要的工具,最终完成用户指定的功能
-
Tools:调用外部功能的函数,例如:调 google 搜索、文件 I/O、Linux Shell 等等
-
LangGraph:工作流开发框架
- LangSmith:过程监控与调试框架
快速开始示例
from langchain.prompts import PromptTemplate
from langchain_community.llms import Tongyi # 导入通义千问Tongyi模型
import dashscope
import os
# 从环境变量获取 dashscope 的 API Key
api_key = os.environ.get('DASHSCOPE_API_KEY')
dashscope.api_key = api_key
# 加载 Tongyi 模型
llm = Tongyi(model_name="qwen-turbo", dashscope_api_key=api_key) # 使用通义千问qwen-turbo模型
# 创建Prompt Template
prompt = PromptTemplate(
input_variables=["product"],
template="What is a good name for a company that makes {product}?",
)
# 新推荐用法:将 prompt 和 llm 组合成一个"可运行序列"
chain = prompt | llm
# 使用 invoke 方法传入输入
result1 = chain.invoke({"product": "colorful socks"})
print(result1)
result2 = chain.invoke({"product": "广告设计"})
print(result2)
说明:PromptTemplate是 LangChain 的提示词模板类chain = prompt | llm可以直接将 prompt 的输出作为 llm 的输入,形成一个可运行的链式结构,简化了原先 LLMChain 的写法
官方文档(以 Python 版为例)
功能模块python.langchain.com/docs/tutori… 文档**python.langchain.com/api_referen… HowTo**python.langchain.com/docs/how_to…
1. 模型 I/O 封装
把不同的模型,统一封装成一个接口,方便更换模型而不用重构代码。
1.1 模型 API: ChatModel
1.1.1 模型初始化
安装依赖:
# !pip install -U langchain
# !pip install -U langchain-openai
# !pip install -U langchain-deepseek
代码示例:
from langchain.chat_models import init_chat_model
model = init_chat_model(model="deepseek-chat", model_provider="deepseek")
response = model.invoke("你是谁")
print(response.content)
💡 划重点:通过模型封装,实现不同模型的统一接口调用
1.1.2 多轮对话 Session 封装
LangChain 提供了统一的消息类型,可以方便地构建多轮对话:
from langchain.schema import (
AIMessage, # 等价于OpenAI接口中的assistant role
HumanMessage, # 等价于OpenAI接口中的user role
SystemMessage # 等价于OpenAI接口中的system role
)
messages = [
SystemMessage(content="你是一名客服人员"),
HumanMessage(content="我是张三"),
AIMessage(content="欢迎!"),
HumanMessage(content="我是谁?")
]
ret = model.invoke(messages)
print(ret.content)
输出结果:
你是张三。很高兴与你交流!有什么问题或者需要帮助的地方吗?
1.1.3 流式输出
对于长文本生成,流式输出可以提升用户体验,让用户实时看到生成内容:
for token in model.stream("你是谁"):
print(token.content, end="")
1.2 模型的输入与输出
1.2.1 Prompt 模板封装
1)PromptTemplate 可以在模板中自定义变量
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(subject='小明'))
输出结果:
===Template===
input_variables=['subject'] input_types={} partial_variables={} template='给我讲个关于{subject}的笑话'
===Prompt===
给我讲个关于小明的笑话
调用 LLM:
from langchain.chat_models import init_chat_model
# 定义 LLM
llm = init_chat_model("deepseek-chat", model_provider="deepseek")
# 通过 Prompt 调用 LLM
ret = llm.invoke(template.format(subject='小明'))
# 打印输出
print(ret.content)
输出示例:
小明去参加考试,监考老师叮嘱:"遇到不会的题目可以跳过去。"
结果考到一半,整个考场的人都听见小明开始做广播体操:"第一节,跳跃运动!"
老师怒吼:"你干嘛呢?"
小明一脸无辜:"不是你说不会的题目就跳吗?我正跳着呢!"
2)ChatPromptTemplate 用模板表示的对话上下文
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate,
)
from langchain.chat_models import init_chat_model
# llm = init_chat_model("gpt-4o-mini", model_provider="openai")
llm = init_chat_model("deepseek-chat", model_provider="deepseek")
template = ChatPromptTemplate.from_messages(
[
SystemMessagePromptTemplate.from_template("你是{product}的客服助手。你的名字叫{name}"),
HumanMessagePromptTemplate.from_template("{query}")
]
)
prompt = template.format_messages(
product="XX店铺",
name="小A",
query="你是谁"
)
print(prompt)
ret = llm.invoke(prompt)
print(ret.content)
输出结果:
[SystemMessage(content='你是XX店铺的客服助手。你的名字叫小A', additional_kwargs={}, response_metadata={}), HumanMessage(content='你是谁', additional_kwargs={}, response_metadata={})]
我是小A,XX店铺的客服助手。如果你有任何问题或者需要帮助,随时可以问我!
3)MessagesPlaceholder 把多轮对话变成模板
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
MessagesPlaceholder,
)
human_prompt = "Translate your answer to {language}."
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)
chat_prompt = ChatPromptTemplate.from_messages(
# variable_name 是 message placeholder 在模板中的变量名
# 用于在赋值时使用
[MessagesPlaceholder("history"), human_message_template]
)
使用示例:
from langchain_core.messages import AIMessage, HumanMessage
human_message = HumanMessage(content="Who is Elon Musk?")
ai_message = AIMessage(
content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
)
messages = chat_prompt.format_prompt(
# 对 "history" 和 "language" 赋值
history=[human_message, ai_message], language="中文"
)
print(messages.to_messages())
调用 LLM:
result = llm.invoke(messages)
print(result.content)
💡 划重点:把 Prompt 模板看作带有参数的函数
1.2.2 从文件加载 Prompt 模板
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_file("example_prompt_template.txt")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(topic='黑色幽默'))
1.3 结构化输出
1.3.1 直接输出 Pydantic 对象
定义输出对象:
from pydantic import BaseModel, Field
# 定义你的输出对象
class Date(BaseModel):
year: int = Field(description="Year")
month: int = Field(description="Month")
day: int = Field(description="Day")
era: str = Field(description="BC or AD")
使用结构化输出:
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain.chat_models import init_chat_model
llm = init_chat_model("deepseek-chat", model_provider="deepseek")
# 定义结构化输出的模型
structured_llm = llm.with_structured_output(Date)
template = """提取用户输入中的日期。
用户输入:
{query}"""
prompt = PromptTemplate(
template=template,
)
query = "2025年十二月20日天气晴..."
input_prompt = prompt.format_prompt(query=query)
structured_llm.invoke(input_prompt)
输出结果:
Date(year=2025, month=12, day=20, era='AD')
1.3.2 输出指定格式的 JSON
# OpenAI 模型的JSON格式
json_schema = {
"title": "Date",
"description": "Formated date expression",
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "year, YYYY",
},
"month": {
"type": "integer",
"description": "month, MM",
},
"day": {
"type": "integer",
"description": "day, DD",
},
"era": {
"type": "string",
"description": "BC or AD",
},
},
}
structured_llm = llm.with_structured_output(json_schema)
structured_llm.invoke(input_prompt)
输出结果:
{'year': 2025, 'month': 12, 'day': 20, 'era': 'AD'}
1.3.3 使用 OutputParser
OutputParser可以按指定格式解析模型的输出
使用 JsonOutputParser:
from langchain_core.output_parsers import JsonOutputParser
parser = JsonOutputParser(pydantic_object=Date)
prompt = PromptTemplate(
template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)
print("\n解析后:")
parser.invoke(output)
使用 PydanticOutputParser:
from langchain_core.output_parsers import PydanticOutputParser
parser = PydanticOutputParser(pydantic_object=Date)
input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)
print("\n解析后:")
parser.invoke(output)
使用 OutputFixingParser 自动纠错:
OutputFixingParser利用大模型做格式自动纠错:
from langchain.output_parsers import OutputFixingParser
from langchain.chat_models import init_chat_model
llm = init_chat_model(model="deepseek-chat", model_provider="deepseek")
# 纠错能力与大模型能力相关
new_parser = OutputFixingParser.from_llm(parser=parser, llm=llm)
bad_output = output.content.replace("4","四")
print("PydanticOutputParser:")
try:
parser.invoke(bad_output)
except Exception as e:
print(e)
print("OutputFixingParser:")
new_parser.invoke(bad_output)
1.4 Function Calling
定义工具函数:
from langchain_core.tools import tool
@tool
def add(a: int, b: int) -> int:
"""Add two integers.
Args:
a: First integer
b: Second integer
"""
return a + b
@tool
def multiply(a: float, b: float) -> float:
"""Multiply two integers.
Args:
a: First integer
b: Second integer
"""
return a * b
绑定工具并调用:
import json
from langchain_core.messages import HumanMessage
llm_with_tools = llm.bind_tools([add, multiply])
query = "3.5的4倍是多少?"
messages = [HumanMessage(content=query)]
output = llm_with_tools.invoke(messages)
print(json.dumps(output.tool_calls, indent=4))
回传 Function Call 的结果:
messages.append(output)
available_tools = {"add": add, "multiply": multiply}
for tool_call in output.tool_calls:
selected_tool = available_tools[tool_call["name"].lower()]
tool_msg = selected_tool.invoke(tool_call)
messages.append(tool_msg)
new_output = llm_with_tools.invoke(messages)
for message in messages:
print(json.dumps(message.model_dump(), indent=4, ensure_ascii=False))
print(new_output.content)
1.5 小结
- LangChain 统一封装了各种模型的调用接口,包括补全型和对话型两种2. LangChain 提供了 PromptTemplate 类,可以自定义带变量的模板3. LangChain 提供了一系列输出解析器,用于将大模型的输出解析成结构化对象4. LangChain 提供了 Function Calling 的封装5. 上述模型属于 LangChain 中较为实用的部分
2. 数据连接封装
2.1 文档加载器:Document Loaders
安装依赖:
# !pip install -U langchain-community pymupdf
代码示例:
from langchain_community.document_loaders import PyMuPDFLoader
loader = PyMuPDFLoader("./data/deepseek-v3-1-4.pdf")
pages = loader.load_and_split()
print(pages[0].page_content)
2.2 文档处理器
2.2.1 TextSplitter
安装依赖:
# !pip install --upgrade langchain-text-splitters
代码示例:
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=200,
length_function=len,
add_start_index=True,
)
paragraphs = text_splitter.create_documents([pages[0].page_content])
for para in paragraphs:
print(para.page_content)
print('-------')
2.3 向量数据库与向量检索
安装依赖:
# !pip install dashscope# !pip install faiss-cpu
完整示例:
import os
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.document_loaders import PyMuPDFLoader
# 加载文档
loader = PyMuPDFLoader("./data/deepseek-v3-1-4.pdf")
pages = loader.load_and_split()
# 文档切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=200,
length_function=len,
add_start_index=True,
)
texts = text_splitter.create_documents(
[page.page_content for page in pages[:1]]
)
# 入库
embeddings = DashScopeEmbeddings(
model="text-embedding-v1", dashscope_api_key=os.getenv("DASHSCOPE_API_KEY")
)
index = FAISS.from_documents(texts, embeddings)
# 检索 top-5 结果
retriever = index.as_retriever(search_kwargs={"k": 5})
docs = retriever.invoke("deepseek v3有多少参数")
for doc in docs:
print(doc.page_content)
print("----")
2.4 小结
1.文档处理部分,建议在实际应用中详细测试后使用2.与向量数据库的连接部分本质是接口封装,向量数据库需要自己选型
📚 下期预告:LCEL(LangChain Expression Language)
在本文中,我们已经初步接触了 LangChain 的核心功能,包括:
- ✅ 模型 I/O 封装(统一接口调用)
- ✅ Prompt 模板管理
- ✅ 结构化输出
- ✅ Function Calling
- ✅ 数据连接与向量检索
你可能已经注意到,在快速开始示例中我们使用了这样的写法:
chain = prompt | llmresult = chain.invoke({"product": "colorful socks"})
这种简洁优雅的链式语法,正是**LCEL(LangChain Expression Language)**的体现!
🎯 下期内容预告
在下一篇文章中,我们将深入探讨LCEL,包括:
- 什么是 LCEL?
- LCEL 核心语法
- 实战应用
- 最佳实践
💡 为什么学习 LCEL?
- 更简洁的代码用更少的代码实现更复杂的功能
- 更好的可维护性清晰的链式结构,易于理解和修改
- 更强的扩展性轻松组合不同的组件,构建复杂的 AI 应用
- 官方推荐LangChain 官方推荐使用 LCEL 作为主要开发方式
📌 提示:如果你对本文内容有任何疑问,或者想提前了解 LCEL 的某个方面,欢迎在评论区留言!