零基础理解LangChain框架
LangChain是一个简化大模型应用开发的框架,支持聊天机器人、智能问答、翻译助手等场景开发。它通过模块化架构,提供模型管理、任务链、记忆存储、代理工具、信息检索和提示词模板等功能。
一、定义
langchain是大模型应用的开发框架,简化大模型应用的开发、测试、评估、运营。不是大模型的开发、训练框架,比如想要从0-1训练一个LLM模型,使用PyTorch框架更合适。
二、用法
(1)安装新版本python,3.10+。 # 安装方法可以问元宝
(2)安装依赖包
pip install langchain
pip install langchain_core
(3)聊天机器人
from langchain.chat_models import init_chat_model
model = init_chat_model("gpt-4o-mini", model_provider="openai")
print(model.invoke("你好"))
(4)翻译小助手
# 使用chat model和prompt模版构建llm应用
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, SystemMessage
model = init_chat_model("gpt-4o-mini", model_provider="openai")
# 定义系统消息(设定GPT角色)
system_message = SystemMessage(content="你是一个专业的中英翻译助手。请将用户输入的中文文字翻译为英文,只翻译最新输入的内容,不要翻译历史内容。")
while True:
user_input = input("请输入要翻译的文字: ")
messages = [
system_message,
HumanMessage(content=user_input)
]
response = model.invoke(messages)
print(f"翻译结果: {response.content}")
提示:代码直接运行可能失败。依赖环境变量中openai的密钥。
三、适用场景
用于大模型应用的开发,比如聊天机器人(聊天+查询互联网资料+查询公司内部系统数据)、智能问答机器人(知识库搜索)、翻译小助手。
一个业务场景示例:
场景:devops领域包含发布系统,发布任务执行失败时,希望能够快速定位原因:系统问题(db故障)、业务服务自身问题(端口没有监听)。如果是业务服务问题,提供具体的报错日志(省去人工登机器找日志)。
解决方案:基于langchain框架开发一个agent,只有一个工具:根据任务链接和机器IP分析失败原因(采用规则匹配识别系统问题,收集服务启动日志后丢给大模型,让大模型总结出报错日志&可能原因)。
四、实现机制&架构
1、核心层,langchain-core
提供:基础抽象(Runnable接口(链式调用时需实现该接口,invoke函数)、提示词模版(xxPromptTemplate)、记忆管理(短期、长期记忆,基于内存、向量数据库、KV数据库)),定义组件的交互标准。
2、集成层,langchain-community
集成第三方sdk。比如openai、deepseek、混元等LLM、Hugging Face的sdk。通过model = ChatOpenAI(xx) 可以快速构建一个LLM客户端。
3、功能层,langchain
提供:链(Chains,提示词模板|LLM|输出格式化)、代理(Agents智能体,AgentExecutor)、检索器(Retrieval,RetrievalQA) 等sdk包。
4、生产层,LangServe、LangSmith
提供:LLM调用的调试、监控。记录每一次LLM调用。
注:LangGraph框架不包含在这里,其侧重解决复杂工作流编排问题,其他问题仍然用上面这些工具包处理。
五、功能模块及作用
1、模型,Models
作用:统一各LLM大模型的接口,包含文本生成(包含聊天、翻译、分类、完形填空等)、对话(聊天单独一个工具类,简化使用)、嵌入(文本转嵌入向量)等任务。
关键组件:
LLM:通用的文本生成模型(如GPT-4、Claude)。
ChatModel:对话专用模型(支持多轮对话,记忆)。
Embedding:文本向量化模型(如OpenAI Embedding、BERT、BGE)。
示例:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model_name="gpt-4-turbo") # 初始化对话模型
2、链,Chains
作用:将多个组件串联为任务流程。
关键组件:
LLMChain:基础链,直接调用LLM。
示例:
from langchain.chat_models import init_chat_model
model = init_chat_model("gpt-4o-mini", model_provider="openai")
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
# 创建提示模板
prompt_template = ChatPromptTemplate([
("system", "你是一个专业的中英翻译助手。请将用户输入的中文文字翻译为英文。"),
MessagesPlaceholder("msgs")
])
# 直接调用
translation_chain = prompt_template | model | StrOutputParser()
result1 = translation_chain.invoke({"msgs": [HumanMessage(content="你好")]})
print(f"翻译 '你好': {result1}")
RetrievalQA:检索增强(RAG)链。
texts = text_splitter.split_documents(documents)
# 1 文本嵌入
embeddings = OpenAIEmbeddings()
# 2 构建向量存储库
docsearch = Chroma.from_documents(texts, embeddings)
# 3 构建检索QA链
llm = ChatOpenAI(model="gpt-4", temperature=0)
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=docsearch.as_retriever(
search_kwargs={
"k": 3
}
)
)
answer = qa.run("langchain是什么?")
print(answer)
SequentialChain:按顺序执行多步骤任务
3、记忆,Memory
作用:管理对话上下文(历史聊天消息),支持多轮交互。
关键组件:
ConversationBufferMemory:基于内存的短期对话缓存对象
RedisMemory:长期存储到Redis
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="chat_history") # 记录对话历史
4、代理,Agents
作用:动态调用工具(API或数据库),实现多步骤推理(ReAct)
关键组件:
ZeroShotAgent:零样本代理
ReActAgent:基于推理-行动循环的代理。
from langchain_openai import ChatOpenAI
from langchain.agents import AgentType, initialize_agent
from langchain.memory import ConversationBufferMemory
from langchain_core.tools import Tool
# 初始化模型
llm = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0,
api_key=api_key,
base_url=base_url
)
# 创建工具列表
tools = [
Tool.from_function(
func=query_order,
name="query_order",
description="根据订单ID查询订单信息"
)
]
# 初始化记忆组件
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 创建ReAct Agent
agent_executor = initialize_agent(
llm=llm,
tools=tools,
memory=memory,
agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
verbose=True,
)
# 执行代理
agent_executor.invoke({"input": "我想查询订单P001的信息,以及商品的信息"})
5、检索器,Retrieval
作用:从外部数据源(知识库,如网页、数据库)检索信息。
流程:网页加载 → 分块 → 向量化 → 存储 → 检索。
示例:
from langchain_community.vectorstores import FAISS
vector_db = FAISS.from_documents(docs, embeddings) # 构建向量数据库
retriever = vector_db.as_retriever() # 创建检索器
6、提示词模板
作用:对大模型设立角色,规范输入格式,动态注入带参数的提示词。
示例:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业的中英翻译助手。请将用户输入的中文文字翻译为英文,只翻译最新输入的内容,不要翻译历史内容。"),
("human", "{input_text}")
])
六、最佳实践
langchain 本质是大模型应用的完整开发框架。通过模块化的组件(提示词、大模型、输出格式化、链、智能体、记忆、检索)和标准化接口(ChatModel、多种大模型)降低大模型应用的开发门槛。最佳实践可以分为4个方面:
最佳实践1、采用LCEL(langchain表达式语言)进行声明式链编程(简化复杂工作流)
通过管道符 | 连接多个组件:Prompt模板、大模型对象、格式化输出,实现快捷组合、原生流支持、异步/批量调用。
代码示例:
# -*- coding: utf-8 -*-
# @Time : 2025/10/03
# @Author : frank
# @File : demo01-lcel.py
# @Description: langchain expression language 示例
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
load_dotenv()
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("科普一个关于{subject}的知识")
output_parser = StrOutputParser()
chain = prompt | llm | output_parser
print(chain.invoke({"subject": "银河系"}))
输出结果:
河系是我们所处的星系,包含着数千亿颗恒星、行星、气体和尘埃。它的形状呈螺旋状,直径大
约为10万光年,厚度约为1000光年。银河系的中心区域有一个超大质量黑洞,名为人马座A*,其质
量约为太阳的400万倍。
最佳实践2:提示工程。提示是LLM输出的关键输入,建议遵守以下技巧:
(1)模板化提示:使用PromptTemplate定义固定格式的Prompt,避免硬编码
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是卡尔萨根,一个著名的天文学家,需回答用户关于天文学的咨询"),
("human", "{user_input}")
])
(2)少样本提示:在提示中加入示例,引导LLM生成符合要求的输出。
prompt = ChatPromptTemplate.from_messages([
("system", "翻译以下文本为法语"),
("human", "Hello World → Bonjour le monde"),
("human", "{text} →")
])
最佳实践3:上下文管理(长短期记忆、检索优化)
(1)短期记忆
# -*- coding: utf-8 -*-
"""
@description: 短期记忆示例 - 使用ConversationBufferWindowMemory保存最近5次对话
@author: frank
@date: 2025-10-03
@version: 1.0
"""
from dotenv import load_dotenv
import os
load_dotenv()
from langchain.chat_models import init_chat_model
from langchain.memory import ConversationBufferWindowMemory
from langchain_core.messages import HumanMessage, AIMessage
model = init_chat_model("gpt-4o-mini", model_provider="openai")
# 创建内存管理器,保存最近2次对话
memory = ConversationBufferWindowMemory(k=2, return_messages=True)
while True:
user_input = input("请输入文字: ")
if user_input == "exit" or user_input == "quit":
break
# 添加用户消息到内存
memory.chat_memory.add_user_message(user_input)
# 获取历史消息 - 使用load_memory_variables确保k参数生效
memory_variables = memory.load_memory_variables({})
messages = memory_variables['history']
# 调用模型
result = model.invoke(messages)
print(result.content)
print("-" * 50)
# 添加AI回复到内存
# 确保content是字符串类型
ai_content = result.content if isinstance(result.content, str) else str(result.content)
memory.chat_memory.add_ai_message(ai_content)
# 显示当前内存中的对话数量
print(f"当前内存中保存了 {len(messages)} 条消息(限制后)")
print(f"原始内存中总共有 {len(memory.chat_memory.messages)} 条消息")
print("=" * 50)
执行结果:
请输入文字: 玩一个成语接龙的游戏
好的,我们来玩成语接龙吧!我来开始,第一个成语是“画龙点睛”。请你接一个
以“睛”字开头的成语。
--------------------------------------------------
当前内存中保存了 1 条消息(限制后)
原始内存中总共有 2 条消息
==================================================
请输入文字: 睛目不凡
很好,你接的成语是“睛目不凡”。接下来我接“凡事预则立”。请你接一个以“立”字开头的成语。
--------------------------------------------------
当前内存中保存了 3 条消息(限制后)
原始内存中总共有 4 条消息
==================================================
请输入文字: 立竿见影
不错,你接的是“立竿见影”。我接“影影绰绰”。请你接一个以“绰”字开头的成语
。
--------------------------------------------------
当前内存中保存了 4 条消息(限制后)
原始内存中总共有 6 条消息
==================================================
请输入文字: 绰绰有余
很好,你接的是“绰绰有余”。我接“余音绕梁”。请你接一个以“梁”字开头的成语
。
--------------------------------------------------
当前内存中保存了 4 条消息(限制后)
原始内存中总共有 8 条消息
==================================================
请输入文字: 停止成语接龙。请输出聊天记录中的成语,从第一个到最后一个。
好的,以下是聊天记录中的成语:
1. 立竿见影
2. 影影绰绰
3. 绰绰有余
4. 余音绕梁
如果你还有其他问题或需要,请告诉我!
--------------------------------------------------
当前内存中保存了 4 条消息(限制后)
原始内存中总共有 10 条消息
==================================================
(2)长期记忆:RAG+向量数据库实现语义检索。
文本切分:使用RecursiveCharacterTextSplitter(递归字符切分)将长文档分割为合适大小的块(如chunk_size=500,chunk_overlap=50),减少检索耗时。
# -*- coding: utf-8 -*-
"""
@description: RAG示例
@author: frank
@date: 2025-10-03
@version: 1.0
"""
from dotenv import load_dotenv
import os
load_dotenv()
from langchain.document_loaders import WebBaseLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
# 检查环境变量
if not os.getenv("OPENAI_API_KEY") or not os.getenv("OPENAI_API_BASE"):
raise ValueError("请设置 OPENAI_API_KEY 和 OPENAI_API_BASE 环境变量")
# 加载网页数据
loader = WebBaseLoader(web_paths=["https://cloud.tencent.com/developer/article/2379888"])
documents = loader.load()
# 打印文档内容
print(documents)
for doc in documents:
print(f'doc: {doc.page_content}...')
# 1 对文档进行预处理:文档切割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200, # 动态调整
chunk_overlap=20, # 重叠为chunk_size的10%
length_function=len, # 使用字符长度计算
separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", " ", ";"] # 中文友好的分隔符
)
# 2 使用传统固定长度切分。段落切分为句子
texts = text_splitter.split_documents(documents)
print("✅ 使用传统固定长度切分")
# 文本嵌入模型
embeddings = OpenAIEmbeddings()
# 3 构建向量存储库
docsearch = Chroma.from_documents(texts, embeddings)
# 4 构建检索QA链
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=docsearch.as_retriever(
search_kwargs={
"k": 3,
}
)
)
# 5 执行查询
while True:
query = input("请输入问题: ")
print(f'query: {query}')
if query == "exit":
break
try:
answer = qa.run(query)
print(answer)
except Exception as e:
print(f"查询出错: {e}")
break
请输入问题: langchain 是什么
query: langchain 是什么
Langchain 是一个开源框架,允许开发人员将大型语言模型(如 GPT-4)与外部
的计算和数据源结合起来。它提供了 Python 和 JavaScript(TypeScript)的
软件包,旨在提升大型语言模型的功能,使其不仅能够回答通用问题,还能从数
据库或文件中提取信息并执行具体操作。Langchain 的设计使得大型语言模型能
够在更广泛的应用环境中进行操作和响应,扩展了它们的应用范围和有效性。
注:检索效果还OK。回答质量不太好,是因为原始文章内容写得不太好,没有写到关键点:大模型应用开发。
最佳实践4:生产环境部署
异步与并发:
使用async/await实现异步调用(如llm.apredict()),提高吞吐量。
使用FastAPI或LangServe部署异步API,支持高并发请求。
异步调用代码示例:
# -*- coding: utf-8 -*-
"""
性能对比示例:同步 vs 异步
"""
import asyncio
import time
from typing import List
# 模拟AI处理时间
def simulate_ai_processing_sync(duration: float) -> str:
"""同步模拟AI处理"""
time.sleep(duration) # 阻塞等待
return f"同步处理完成,耗时 {duration} 秒"
async def simulate_ai_processing_async(duration: float) -> str:
"""异步模拟AI处理"""
await asyncio.sleep(duration) # 非阻塞等待
return f"异步处理完成,耗时 {duration} 秒"
def sync_benchmark(requests: int, duration: float) -> float:
"""同步性能测试"""
start_time = time.time()
for i in range(requests):
result = simulate_ai_processing_sync(duration)
print(f"同步请求 {i+1}: {result}")
end_time = time.time()
return end_time - start_time
async def async_benchmark(requests: int, duration: float) -> float:
"""异步性能测试"""
start_time = time.time()
# 创建所有异步任务
tasks = []
for i in range(requests):
task = simulate_ai_processing_async(duration)
tasks.append(task)
# 并发执行所有任务
results = await asyncio.gather(*tasks)
for i, result in enumerate(results):
print(f"异步请求 {i+1}: {result}")
end_time = time.time()
return end_time - start_time
async def main():
"""主函数"""
requests = 5
duration = 1.0 # 每个请求1秒
print("=== 同步处理测试 ===")
sync_time = sync_benchmark(requests, duration)
print(f"同步总耗时: {sync_time:.2f} 秒")
print(f"平均每个请求: {sync_time/requests:.2f} 秒")
print("\n=== 异步处理测试 ===")
async_time = await async_benchmark(requests, duration)
print(f"异步总耗时: {async_time:.2f} 秒")
print(f"平均每个请求: {async_time/requests:.2f} 秒")
print(f"\n=== 性能提升 ===")
improvement = sync_time / async_time
print(f"性能提升: {improvement:.2f}x")
print(f"时间节省: {((sync_time - async_time) / sync_time * 100):.1f}%")
if __name__ == "__main__":
asyncio.run(main())
输出结果:
=== 同步处理测试 ===
同步请求 1: 同步处理完成,耗时 1.0 秒
同步请求 2: 同步处理完成,耗时 1.0 秒
同步请求 3: 同步处理完成,耗时 1.0 秒
同步请求 4: 同步处理完成,耗时 1.0 秒
同步请求 5: 同步处理完成,耗时 1.0 秒
同步总耗时: 5.00 秒
平均每个请求: 1.00 秒
=== 异步处理测试 ===
异步请求 1: 异步处理完成,耗时 1.0 秒
异步请求 2: 异步处理完成,耗时 1.0 秒
异步请求 3: 异步处理完成,耗时 1.0 秒
异步请求 4: 异步处理完成,耗时 1.0 秒
异步请求 5: 异步处理完成,耗时 1.0 秒
异步总耗时: 1.00 秒
平均每个请求: 0.20 秒
=== 性能提升 ===
性能提升: 4.99x
时间节省: 79.9%
FastAPI 示例:
# -*- coding: utf-8 -*-
"""
@description: LangServe 简单示例 - 通过URL参数生成标语
@author: frank
@date: 2025-10-03
@version: 1.0
"""
from dotenv import load_dotenv
import os
load_dotenv()
# 检查环境变量
if not os.getenv("OPENAI_API_KEY") or not os.getenv("OPENAI_API_BASE"):
raise ValueError("请设置 OPENAI_API_KEY 和 OPENAI_API_BASE 环境变量")
from fastapi import FastAPI, Query
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# 创建 FastAPI 应用
app = FastAPI(title="LangServe 笑话生成器", version="1.0.0")
# 初始化组件
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("写一个关于{subject}的笑话")
output_parser = StrOutputParser()
# 创建处理链
chain = prompt | llm | output_parser
@app.get("/joke")
async def get_joke(subject: str = Query(..., description="笑话主题")):
"""生成关于指定主题的笑话"""
try:
# 使用链处理输入
result = await chain.ainvoke({"subject": subject})
return {"joke": result, "subject": subject}
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
import uvicorn
print("启动 LangServe 服务...")
print("访问 http://localhost:8000/joke?subject=人工智能 测试")
print("访问 http://localhost:8000/docs 查看 API 文档")
uvicorn.run(app, host="0.0.0.0", port=8000)
输出结果:
http://localhost:8000/joke?subject=人工智能
{"joke":"为什么人工智能总是很懒?\n\n因为它总是希望“算法”能解决所有问题!","subject":"人工智能"}
更多推荐
所有评论(0)