LangChain实战:快速搭建大语言模型应用
1. 从零开始:用LangChain快速搭建大语言模型应用
最近在折腾大语言模型应用开发时,发现LangChain这个框架确实能极大提升开发效率。作为一个长期奋战在一线的开发者,我想分享下如何用LangChain快速搭建一个可用的LLM应用。不同于官方文档的学院派风格,我会用更接地气的方式,结合实战经验来讲解。
LangChain本质上是一个为大语言模型应用开发设计的框架,它把常见的开发模式抽象成组件和链条(Chain)。想象一下乐高积木,每个组件就像一块积木,而Chain就是把这些积木按照特定顺序连接起来的方式。这样做最大的好处是,开发者不用每次都从头造轮子,可以直接使用现成的模块快速搭建应用。
2. 环境准备与工具选型
2.1 基础环境配置
首先需要安装LangChain的核心包。建议使用Python 3.8及以上版本,太老的Python版本可能会有兼容性问题。安装命令很简单:
pip install langchain langchain-community
这里解释下这两个包的区别:
- langchain是核心框架
- langchain-community包含社区维护的各种第三方集成
注意:建议在虚拟环境中安装,避免污染全局Python环境。可以用venv或conda创建隔离环境。
2.2 模型提供商选择
LangChain支持多种大模型提供商,这里列举几个常用的:
# OpenAI (ChatGPT)
pip install langchain-openai
# Hugging Face
pip install langchain-huggingface
# 阿里云通义千问
pip install langchain-qwq
选择模型提供商时需要考虑几个因素:
- 模型性能:不同模型的智能程度差异很大
- API成本:商用API通常按token收费
- 响应速度:实时应用对延迟敏感
- 数据隐私:某些场景对数据出境有要求
以我的经验,如果是个人项目或测试,可以从通义千问开始,它的免费额度比较友好。如果是商业项目,GPT-4可能是更稳妥的选择。
3. 第一个LangChain应用实战
3.1 初始化模型连接
以通义千问为例,首先需要设置API密钥:
import os
from langchain_community.chat_models.tongyi import ChatTongyi
os.environ["DASHSCOPE_API_KEY"] = "你的API_KEY"
model = ChatTongyi(model="qwen-plus")
这里有几个关键点:
- API密钥建议通过环境变量传入,不要硬编码在代码中
qwen-plus是模型名称,不同提供商模型命名规则不同- 首次使用需要到对应平台申请API密钥
3.2 构建提示词模板
LangChain提供了强大的提示词模板功能:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个精通{topic}的资深技术专家。"),
("user", "请用三句话解释一下什么是{concept}。")
])
这个模板有几个特点:
- 使用
{}定义变量,实际调用时动态填充 - 支持多角色对话(system/user/ai)
- system消息用于设定AI的角色和背景
实战技巧:system提示词对输出质量影响很大。根据我的经验,明确指定AI的角色和专业领域,能显著提升回答的专业性。
3.3 创建处理链
LangChain的核心概念就是Chain(链):
from langchain_core.output_parsers import StrOutputParser
output_parser = StrOutputParser()
chain = prompt | model | output_parser
这个 | 操作符看起来像Unix管道,确实概念也很相似 - 数据从左向右流动:
- 首先输入数据填充prompt模板
- 然后将完整prompt发送给模型
- 最后用解析器处理模型输出
3.4 调用模型获取响应
调用方式有两种,根据场景选择:
# 一次性获取完整响应(适合非实时场景)
response = chain.invoke({"topic": "Python", "concept": "列表"})
print(response)
# 流式输出(适合实时交互场景)
for chunk in chain.stream({"topic": "人工智能", "concept": "神经网络"}):
print(chunk, end="", flush=True)
流式输出的优势:
- 用户体验更好,像打字机一样逐步显示
- 对于长响应可以提前看到部分结果
- 在某些平台上能减少响应感知延迟
4. 核心组件深度解析
4.1 模型封装详解
不同的模型提供商有不同的初始化方式:
# 通义千问
from langchain_community.chat_models.tongyi import ChatTongyi
model = ChatTongyi(model="qwen-plus")
# OpenAI
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4")
# Hugging Face
from langchain_community.chat_models.huggingface import ChatHuggingFace
model = ChatHuggingFace(model="meta-llama/Llama-2-7b-chat-hf")
关键参数说明:
temperature:控制输出的随机性(0-1)max_tokens:限制响应长度top_p:核采样参数,影响多样性
经验之谈:temperature设为0.7左右通常能在确定性和创造性之间取得不错平衡。对于需要精确答案的场景,可以降到0.3以下。
4.2 提示词工程技巧
好的提示词是获得优质回答的关键。LangChain的提示词模板支持多种高级功能:
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
# 少量示例提示词
examples = [
{"input": "2+2", "output": "4"},
{"input": "5*3", "output": "15"}
]
example_prompt = ChatPromptTemplate.from_messages([
("human", "{input}"),
("ai", "{output}")
])
few_shot_prompt = FewShotChatMessagePromptTemplate(
example_prompt=example_prompt,
examples=examples
)
这种少量示例(few-shot)方式特别适合:
- 定义特定的回答格式
- 教会模型特定领域的推理方式
- 处理模型容易出错的边缘情况
4.3 输出解析器应用
除了简单的字符串解析,LangChain还支持结构化输出:
from langchain_core.output_parsers import CommaSeparatedListOutputParser
parser = CommaSeparatedListOutputParser()
chain = prompt | model | parser
result = chain.invoke({"topic": "编程语言", "concept": "主流语言"})
# 返回的是列表而不是字符串
常用输出解析器类型:
StrOutputParser- 普通文本CommaSeparatedListOutputParser- 逗号分隔列表StructuredOutputParser- 复杂JSON结构RegexParser- 用正则表达式提取内容
5. 实战中的常见问题与解决方案
5.1 超时与重试机制
网络请求难免会遇到超时,LangChain提供了自动重试功能:
from langchain_community.chat_models.tongyi import ChatTongyi
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def safe_invoke():
model = ChatTongyi(model="qwen-plus", request_timeout=30)
return model.invoke("请用中文回答")
response = safe_invoke()
这个配置表示:
- 最多重试3次
- 等待时间指数增长(4s, 8s, 16s)
- 单次请求超时30秒
5.2 速率限制处理
调用商用API常会遇到速率限制,解决方案:
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.callbacks import CallbackManager
from langchain_core.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
model = ChatTongyi(
model="qwen-plus",
streaming=True,
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),
max_retries=5,
retry_min_seconds=1,
retry_max_seconds=10
)
关键参数:
max_retries:最大重试次数retry_min/max_seconds:重试间隔范围streaming:启用流式可以降低超时概率
5.3 本地模型部署方案
如果对数据隐私要求高,可以考虑本地部署:
from langchain_community.chat_models.huggingface import ChatHuggingFace
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "meta-llama/Llama-2-7b-chat-hf"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
hf_model = ChatHuggingFace(model=model, tokenizer=tokenizer)
本地部署的优缺点:
- 优点:数据不出内网,长期成本可能更低
- 缺点:需要GPU资源,推理速度较慢
6. 性能优化与高级技巧
6.1 缓存机制应用
重复查询相同内容时,使用缓存可以显著节省成本:
from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache
set_llm_cache(InMemoryCache())
# 第一次调用会真实请求API
response1 = chain.invoke({"topic": "Python", "concept": "装饰器"})
# 第二次相同输入会直接从缓存返回
response2 = chain.invoke({"topic": "Python", "concept": "装饰器"})
LangChain支持的缓存后端:
InMemoryCache- 内存缓存,重启失效SQLiteCache- 本地数据库缓存RedisCache- Redis缓存,适合分布式场景
6.2 异步并发调用
对于批量处理场景,异步调用可以大幅提升效率:
import asyncio
from langchain_core.runnables import RunnableLambda
async def batch_invoke():
chain = prompt | model | output_parser
inputs = [
{"topic": "Python", "concept": "生成器"},
{"topic": "Go", "concept": "协程"},
{"topic": "Java", "concept": "Stream API"}
]
return await chain.abatch(inputs)
results = asyncio.run(batch_invoke())
异步调用的注意事项:
- 检查API提供商的并发限制
- 合理控制并发量,避免触发速率限制
- 错误处理更复杂,需要单独捕获每个任务异常
6.3 监控与日志记录
生产环境需要完善的监控:
from langchain.callbacks.tracers import LangChainTracer
from langchain.callbacks.manager import collect_runs
tracer = LangChainTracer()
with collect_runs() as cb:
response = chain.invoke(
{"topic": "DevOps", "concept": "CI/CD"},
config={"callbacks": [tracer]}
)
print(cb.traced_runs[0].outputs)
监控的关键指标:
- 请求延迟
- Token使用量
- 错误率
- 速率限制触发次数
7. 项目架构设计建议
7.1 模块化设计
大型项目应该采用模块化设计:
my_llm_app/
├── chains/
│ ├── qa_chain.py
│ └── summarization_chain.py
├── models/
│ └── llm_manager.py
├── prompts/
│ ├── system_prompts.py
│ └── few_shot_examples.py
└── main.py
各模块职责:
chains/:存放各种业务链models/:模型初始化与管理prompts/:提示词模板管理main.py:应用入口
7.2 配置管理
建议使用配置文件管理参数:
# config.yaml
models:
tongyi:
api_key: ${TONGYI_API_KEY}
model_name: qwen-plus
temperature: 0.7
prompts:
tech_expert:
system: "你是一个精通{topic}的资深技术专家"
user: "请用三句话解释{concept}"
然后在代码中加载配置:
import yaml
from langchain_core.prompts import ChatPromptTemplate
with open("config.yaml") as f:
config = yaml.safe_load(f)
prompt = ChatPromptTemplate.from_messages([
("system", config["prompts"]["tech_expert"]["system"]),
("user", config["prompts"]["tech_expert"]["user"])
])
7.3 测试策略
LLM应用测试的挑战:
- 输出具有不确定性
- 评估标准主观性强
- 运行成本高
建议的测试方案:
- 对确定性逻辑(如输入处理)写单元测试
- 对模型输出进行抽样人工评估
- 使用评估框架如RAGAS进行自动化评估
def test_chain_output_format():
response = chain.invoke({"topic": "Test", "concept": "Test"})
assert isinstance(response, str)
assert len(response.split("。")) == 3 # 检查是否三句话
8. 从Demo到生产的关键考量
当应用要从演示版升级到生产环境时,有几个关键点需要考虑:
-
错误处理与重试 :生产环境必须有完善的错误处理机制,特别是对于网络不稳定的情况。建议实现指数退避的重试策略。
-
性能监控 :需要监控API调用延迟、错误率和token使用情况。可以使用Prometheus等工具采集指标。
-
成本控制 :商用API按token计费,需要:
- 实现使用量告警
- 考虑缓存常用查询结果
- 对长文本进行适当截断
-
安全防护 :
- 对用户输入进行严格的过滤和清理
- 防范提示词注入攻击
- 敏感数据脱敏处理
-
可观测性 :
- 记录完整的请求/响应日志(注意隐私)
- 实现追踪链式调用过程的能力
- 设置合理的日志保留策略
# 生产级错误处理示例
from tenacity import retry, stop_after_attempt, wait_exponential
from langchain_core.exceptions import LangChainError
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10),
retry=retry_if_exception_type(LangChainError)
)
def safe_invoke(chain, input_dict):
try:
return chain.invoke(input_dict)
except LangChainError as e:
log_error(e)
raise
9. 扩展应用场景
LangChain不仅限于简单的问答场景,还可以支持更复杂的应用:
9.1 文档问答系统
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_core.runnables import RunnablePassthrough
# 加载并分割文档
loader = WebBaseLoader("https://example.com/doc")
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# 创建向量存储
vectorstore = FAISS.from_documents(docs, embedding_model)
retriever = vectorstore.as_retriever()
# 构建问答链
qa_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| model
| output_parser
)
9.2 数据分析Agent
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain.tools import Tool
def query_database(query: str) -> str:
# 实现数据库查询逻辑
return "查询结果"
tools = [
Tool(
name="db_query",
func=query_database,
description="用于查询业务数据库"
)
]
agent = create_openai_tools_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)
result = agent_executor.invoke({
"input": "我们上个月销售额最高的产品是什么?"
})
9.3 自动化工作流
from langchain_core.runnables import RunnableBranch
def route_based_on_topic(input_dict):
if "Python" in input_dict["topic"]:
return python_chain
else:
return general_chain
branch_chain = RunnableBranch(
(lambda x: "Python" in x["topic"], python_chain),
general_chain
)
full_chain = {
"topic": lambda x: x["topic"],
"concept": lambda x: x["concept"]
} | branch_chain
10. 持续学习与资源推荐
要深入掌握LangChain,我推荐以下学习路径:
-
官方文档 :虽然有些部分比较简略,但架构说明很值得细读
- 重点阅读:Chain、Memory、Agent等核心概念
-
开源项目 :
- LangChain模板库:大量现成的应用示例
- LangSmith:官方的调试和监控平台(目前处于beta)
-
进阶书籍 :
- 《LangChain in Action》:实战案例丰富
- 《Prompt Engineering for Developers》:深入提示词工程
-
社区资源 :
- LangChain官方Discord频道
- 相关技术论坛的LLM板块
-
实践建议 :
- 从简单应用开始,逐步增加复杂度
- 建立自己的代码片段库
- 参与开源项目贡献
最后分享一个我在实际项目中的体会:LangChain虽然降低了开发门槛,但要构建真正可用的生产级应用,仍然需要对底层原理有扎实的理解。建议在使用框架的同时,也要学习Transformer架构、注意力机制等基础知识,这样才能在遇到问题时更快找到解决方案。
更多推荐

所有评论(0)