LangChain的 六大核心组件与 RAG 知识库构建

引言:为什么要用 LangChain?

随着大语言模型(LLM)的蓬勃发展,开发者面临着 API 标准各异、模型缺乏外部知识、提示词管理困难等现实痛点。LangChain 由此诞生。它本身并非是一个新的大模型,而是一个标准化的 LLM 应用开发框架。它通过为各种 LLM 提供统一的接口,将模型、提示词、数据源、记忆体等组件标准化地"串联"起来,快速构建复杂的生成式 AI 应用。

本文将抛开概念堆砌,从核心组件解析、重构后的实战代码、工程化架构逻辑三个维度,系统地带您掌握 LangChain 的开发内功。


一、解密 LangChain 的六维组件架构

一个成熟的 LangChain 应用,依赖六大核心组件各司其职:

  • Models(模型):屏蔽底层 API 差异,提供统一的模型调用入口。

  • Prompts(提示词):管理输入大模型的提示内容,支持结构化和复用。

  • Chains(链):将模型、提示词、甚至其他链连接成一条执行流水线。

  • Agents(代理):让大模型化身为"智能大脑",自主决定是否调用外部工具。

  • Memory(记忆):突破大模型无状态限制,存储和读取短期或长期的对话记录。

  • Indexes(索引):赋予大模型处理非结构化外部私有数据的能力,这是 RAG 技术的基石。


二、模型层(Models):统一接口与消息结构

在工程实践中,我们常常需要切换不同的模型(如从通义千问切换到百川大模型)。LangChain 的模型层提供了统一的调用接口

1. LLMs 与 Chat Models

目前大模型主要以两种形式提供服务:

  • LLMs:输入一串纯文本,输出也是一串纯文本。

  • Chat Models :输入是有结构的聊天消息列表 ,输出也是特定的消息对象。这一点非常重要,它直接对应了多轮对话上下文记忆的数据结构。

实战代码

我们使用 ChatOpenAI 适配国内主流通义千问模型进行演示。通过 stream 方法实现类打字机的流式输出。

python 复制代码
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

llm = ChatOpenAI(
    model="qwen-max",
    api_key=os.getenv("ALIBABA_API_KEY"),
    base_url=os.getenv("ALIBABA_BASE_URL")
)

# 1. 流式聊天模式
for chunk in llm.stream("请用一首五言绝句描述春日的生机。"):
    print(chunk.content, end="")

# 2. 多轮对话的消息结构
messages = [
    SystemMessage("你是一个精通金融知识的资深顾问。"),
    HumanMessage("我对今年黄金的走势很关心,有什么建议吗?"),
    AIMessage("黄金通常被视为避险资产,受美元走势和地缘政治影响较大。建议关注美联储的利率决议。"),
    HumanMessage("那在黄金投资中,我需要注意哪些风险?"),
]
response = llm.invoke(messages)
print(f"\n[上下文推理结果]:\n{response.content}")

(注:上述代码通过向模型传入 HumanMessageAIMessage 的交替列表,完美复现了多轮对话的历史上下文环境。)

2. 文本嵌入模型(Embeddings)

嵌入模型用于将人类语言转换为高维浮点数向量。这些向量之间的距离代表语义的相似度,是实现检索增强生成(RAG)和数据去重的基础。

python 复制代码
from langchain_community.embeddings import DashScopeEmbeddings

embeddings = DashScopeEmbeddings(
    dashscope_api_key=os.getenv('ALIBABA_API_KEY'),
    model="text-embedding-v1"
)

vector = embeddings.embed_query("大语言模型正在改变各行各业的开发范式。")
print(f"生成的向量维度为:{len(vector)}")

三、提示词层(Prompts):让大模型"听懂"任务

想要模型输出准确,提示词结构必须严谨。LangChain 提供了两种核心的提示词构建范式:零样本(Zero-shot)和少样本(Few-shot)。

1. 少样本提示(Few-shot)的原理剖析

在构建少样本提示词时,标准的结构化公式是: 前缀(角色与任务) + 示例对(输入与输出) + 后缀(当前用户输入)

这种设计可以极大地激发大模型的推理和模仿能力。我们重构一个寻找同义词的业务场景:

python 复制代码
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate

# 定义基础示例
examples = [
    {"word": "开心", "synonym": "愉悦"},
    {"word": "震撼", "synonym": "震惊"},
    {"word": "珍贵", "synonym": "宝贵"},
]

example_prompt = PromptTemplate(
    input_variables=["word", "synonym"],
    template="原词:{word}\n近义词:{synonym}\n"
)

# 组装少样本模板
few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="你是一个中文词汇专家,请参考以下示例,准确找出给定词汇的近义词。",
    suffix="原词:{input}\n近义词:",
    input_variables=["input"]
)

final_prompt = few_shot_prompt.format(input="辉煌")
print(final_prompt)
# 执行后,控制台将清晰展示【前缀】+【示例列表】+【当前输入】的完整拼接结构。

四、链式调用层(Chains):构建复杂业务流

在复杂的业务逻辑中,往往需要大模型执行**"先写一篇文章,再从中提炼摘要,最后翻译成英文"**的流程。LangChain 的 Chain 组件就是处理这类任务的"流水线"。

工程化语法演变 :经过框架版本迭代,现在推荐使用 |(管道符) 来组合链。这种 Linux 管道风格的写法,极大地提升了代码的可读性和解耦性。

python 复制代码
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

# 第一步链:生成内容
prompt1 = PromptTemplate.from_template("请根据主题 {topic},写一篇 80 字左右的科普短文。")
# 第二步链:提炼标题
prompt2 = PromptTemplate.from_template("根据上面的短文内容:\n{content}\n请提炼一个不超过 8 个字的标题。")

# 组合链条
chain = prompt1 | llm | prompt2 | llm | StrOutputParser()

# 只需要传入初始的 {topic} 变量,后续的 {content} 会自动由上一步的输出传递
result = chain.invoke({"topic": "5G 通信技术的优势"})
print(result)

五、代理层(Agents):大模型的"手脚"进化

大模型本身存在知识截止日期、无法进行复杂数学计算、无法查询实时天气等严重局限。Agents(代理) 赋予了大模型调用外部工具的能力。

1. 代理的决策流程

实践中,代理的执行通常包含四个步骤:

  1. 用户请求(如:"帮我计算 24 × 12 的结果,顺便查一下上海今天的天气。")

  2. 大模型"大脑"解析:判断需要调用两个工具,并解析出工具所需的参数。

  3. 执行工具调用:LangChain 执行计算函数和天气 API 请求。

  4. 集成回复:大模型拿到工具返回的数据,将其合成为流畅的人类语言。

2. 自定义工具(@tool 装饰器)

我们可以用 @tool 装饰器将普通的 Python 函数直接封装成 LangChain 可识别的工具,并自动提取函数的参数说明。

python 复制代码
from langchain.tools import tool
from langchain.agents import create_agent

# 定义自定义工具1:数学计算
@tool
def calculator(a: int, b: int) -> int:
    """用于计算两个整数的乘积。"""
    print(f"正在调用数学工具:{a} × {b}")
    return a * b

# 定义自定义工具2:模拟天气预报
@tool
def weather_lookup(city: str) -> str:
    """获取指定城市的实时温度(模拟数据)。"""
    temp_map = {"北京": 25, "上海": 29, "深圳": 33}
    temp = temp_map.get(city, 23)
    return f"{city} 当前气温为 {temp} 摄氏度。"

# 构建代理
agent = create_agent(
    model=llm,
    tools=[calculator, weather_lookup],
    system_prompt="你是一个多面手助手,可根据用户指令自主决定调用数学或天气工具。"
)

# 用户一次性提出复合指令
user_msgs = {"messages": [{"role": "user", "content": "帮我算 15 * 8 的结果,然后查一下北京今天的气温。"}]}
for step in agent.stream(user_msgs):
    print(step)
    # 流式输出将清晰展示:解析工具 -> 执行工具 -> 最后回答的完整过程。

六、记忆层(Memory):突破"瞬忘"的魔咒

大模型的底层接口本身是无状态的,如果不做特殊处理,每次提问都是独立的。因此,记忆层是构建对话机器人的核心支柱。

1. 短期记忆

ChatMessageHistory 提供了一个简单的列表容器,存储当前运行环境内的消息记录。

2. 长期记忆(数据库持久化)

在实际商业化应用中,我们需要将不同用户的对话保存在数据库中。LangChain 结合 langgraph 框架提供了检查点(Checkpoint)机制 。我们通过设置 thread_id(用户会话ID),可以将对话状态持久化到 MySQL 等数据库中。

(注:下面的代码使用内存代替数据库进行模拟,其原理与挂载 MySQL 检查点完全一致)

python 复制代码
from langgraph.checkpoint.memory import InMemorySaver # 此处用内存模拟数据库持久化

# 初始化持久化检查点
checkpointer = InMemorySaver()
agent_memory = create_agent(model=llm, tools=[], checkpointer=checkpointer)

# 模拟用户1的独立会话 ID
user1_config = {"configurable": {"thread_id": "user_001"}}

# 第一轮对话:存储用户信息
agent_memory.invoke(
    {"messages": [{"role": "user", "content": "我叫李雷,今天第一次接触LangChain。"}]},
    config=user1_config
)

# 第二轮对话:读取历史上下文
response = agent_memory.invoke(
    {"messages": [{"role": "user", "content": "还记得我叫什么名字吗?我在学什么?"}]},
    config=user1_config
)
print(response['messages'][-1].content) # 输出结果将完美回忆起上一条信息

七、索引层(Indexes):搭建本地 RAG 知识库

RAG(检索增强生成)是当前大模型落地最火热的方向,它允许大模型回答它在训练数据中没见过的"企业私有知识"。

1. 核心步骤:文档加载与语义分割

在工程实践中,当面对数十页的 PDF 或 TXT 文档时,直接喂给大模型会导致 Token 溢出 。因此必须使用文本分割器。

需要重点强调的是 :普通的 CharacterTextSplitter 会按指定的字符长度生硬截断,极易将一段完整的话切为两半。业界标准做法是使用 RecursiveCharacterTextSplitter(递归字符分割器)

  • 它会优先尝试使用段落符(\n\n)切割。

  • 如果切出来的片段过长,再尝试用句号()切割。

  • 如果还过长,再降低到逗号(),直到切分出的文本块足够短且语义完整

python 复制代码
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 1. 加载本地文本文件
loader = TextLoader("./data/rag_sources.txt")
documents = loader.load()

# 2. 递归分割器(保证语义最大化不被破坏)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20)
chunks = text_splitter.split_documents(documents)
print(f"成功切分成 {len(chunks)} 个语义块。")

2. 向量化存储与检索

切分后,我们需要使用嵌入模型 将这些块转化为高维向量,并存入专用的向量数据库 (如 Chroma、FAISS)。

当用户提问时,系统会将用户的问句向量化,并在数据库中找到语义最相似的 Top N 个文档片段作为"参考资料",最后将"参考资料 + 用户提问"打包发送给大模型生成最终回答。

python 复制代码
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import DashScopeEmbeddings

embeddings = DashScopeEmbeddings(dashscope_api_key=os.getenv('ALIBABA_API_KEY'), model="text-embedding-v1")
vectorstore = Chroma.from_documents(documents=chunks, embedding=embeddings)

# 检索测试
query = "LangChain 的索引层主要解决什么业务问题?"
retriever = vectorstore.as_retriever(search_kwargs={'k': 2})
top_results = retriever.invoke(query)
print(f"匹配到的Top 2片段:{top_results}")

八、结构化输出(Structured Output):向业务 API 对接

在大多数生产环境中,大模型直接返回"自然语言文本"往往会增加后续解析的复杂度。LangChain 提供了一整套结构化输出机制,通过 Pydantic 数据模型作为"约束框架",强制大模型以 JSON 格式返回所需的数据。

  • 底层原理:LangChain 将 Pydantic 模型转化为大模型内部的"工具调用(Tool Call)"结构。大模型不会生成文本,而是生成一个结构化的参数对象,从而实现数据精准抽取。
python 复制代码
from typing import Optional
from pydantic import BaseModel, Field

# 1. 定义提取目标的数据结构
class UserProfile(BaseModel):
    full_name: str = Field(description="用户的真实姓名")
    age: int = Field(description="用户的年龄,单位岁")
    city: Optional[str] = Field(description="用户目前的居住城市")

# 2. 将数据结构绑定到代理上
agent = create_agent(
    model=llm,
    response_format=UserProfile,
)

# 3. 输入一段非结构化的自然语言描述
raw_text = "你好,我叫张三,今年31岁,之前在北京互联网大厂工作,今年刚刚搬到杭州发展。"
response = agent.invoke({"messages": [{"role": "user", "content": raw_text}]})

# 4. 直接获取结构化的 Python 对象
profile = response['structured_response']
print(f"姓名:{profile.full_name}, 年龄:{profile.age}, 城市:{profile.city}")
# 输出:姓名:张三, 年龄:31, 城市:杭州

结语:LangChain 的"积木哲学"与工程化落地

纵观 LangChain 的 6 大核心组件(模型、提示词、链、代理、记忆、索引)以及结构化输出设计,其本质都在传达一种**"积木式"的开发思维**。

  • 如果您需要构建一个智能客服,您可以 Memory + Chat Models

  • 如果您需要连接企业内部数据库,您可以 Agents + 自定义工具

  • 如果您需要解答私有文档问题,您可以 Indexes + Embeddings + Vector DB + Chain

掌握了这些核心组件及其背后的架构逻辑,就等于拿到了大模型应用开发的"标准工程图纸"。在这个大模型技术飞速迭代的时代,LangChain 的这六大核心模块依然是绝大多数 AI 应用不可或缺的地基,值得所有 AI 开发者深入学习与实践。

相关推荐
华清远见成都中心1 小时前
卷积神经网络(CNN)为什么能够识别图像?
人工智能·深度学习·cnn
派拉软件1 小时前
派拉AIGS应用场景解析:在客户实际环境中,AI Agent如何做到“可控、可管、可审“
大数据·人工智能
创世宇图1 小时前
DeepSeek API涨价的技术归因与开发者成本优化实操
人工智能·deepseek
QAQo7T2 小时前
Python组蓝桥杯备赛超详细知识点总结笔记_排序算法篇
笔记·python·算法·蓝桥杯·排序算法
四六的六2 小时前
端侧模型多端部署实战:从格式转换到灰度发布,Web 和移动端统一部署流水线
前端·人工智能·大模型·ai编程·ai模型·ai产品·端侧ai
醉颜凉2 小时前
蓝桥杯2025年第十六届省赛真题-最大数字 Python题解
python·职场和发展·蓝桥杯
深小乐2 小时前
用AI做了6首歌曲MV后,我最大的收获不是会做了,而是干中学
人工智能
郑午时光2 小时前
全球首发!2026年适合IP短剧长视频的AI视频生成工具,即梦seedance2.5轻松做短剧
人工智能·tcp/ip·音视频
智道天成2 小时前
浙江代办食品生产许可证怎么办理,哪些企业可以申请全程代办服务
人工智能