LangChain 从零入门,结合这个项目讲
1. 先说结论:LangChain 到底是什么
LangChain 是一个用来开发大模型应用的框架。
如果只用一句话解释它,可以说:
LangChain 帮我们把“大模型、提示词、知识库、工具、Agent、输出处理”这些零散能力连接起来,做成一个完整 AI 应用。
很多初学者一看到 LangChain,会误以为它本身就是“大模型”。
其实不是。
LangChain 更像:
- 一个组织代码的框架
- 一个搭建 AI 工作流的工具箱
- 一个把模型和外部系统接起来的中间层
它不负责“创造模型”,而是负责“更好地使用模型”。
2. 如果没有 LangChain,会发生什么
假设你要自己写一个文档问答系统。
你可能要手动做这些事:
- 调用大模型 API
- 读 PDF / TXT / DOCX 文件
- 切分文本
- 生成 embedding
- 存入向量库
- 查询时再检索相关文本
- 把检索结果拼进 prompt
- 调模型生成答案
- 处理输出格式
- 如果还要 Agent,再自己写工具调用逻辑
这些当然都能自己写,但会比较散。
LangChain 的价值就在于:
- 提供统一抽象
- 提供现成组件
- 提供常见链路组合方式
- 降低 AI 应用开发成本
3. LangChain 里最核心的几个概念
刚学 LangChain,不要一上来就去看所有 API。
你先抓住这几个关键对象就够了:
- Model
- Prompt
- Output Parser
- Document
- Embeddings
- Vector Store
- Retriever
- Chain
- Tool
- Agent
下面我们一个个讲。
4. Model:模型
模型就是 LangChain 要调用的“大脑”。
在 LangChain 里,常见模型有两大类:
- Chat Model 用于聊天、问答、总结、推理
- Embedding Model 用于把文本转成向量
4.1 这个项目里的聊天模型
在这个项目里,聊天模型主要在:
backend/app/utils/factory.py
这里用的是:
ChatTongyi
也就是阿里云通义模型的 LangChain 封装。
代码的意思可以简单理解成:
给我一个可对话的大模型实例,后面 RAG 总结和 Agent 都会用它。
4.2 这个项目里的 embedding 模型
同一个文件里还创建了:
OllamaEmbeddings
它负责:
把文本转成向量,供向量检索使用
所以你要记住:
- 聊天模型负责“说话”
- embedding 模型负责“向量化”
它们不是一回事。
5. Prompt:提示词模板
Prompt 就是你发给模型的指令。
但在项目里,通常不会每次都手写一整段字符串,而是用模板。
LangChain 里常见的 Prompt 类型包括:
PromptTemplateChatPromptTemplate
5.1 PromptTemplate
适合普通文本模板,例如:
请根据以下资料回答问题:
问题:{input}
资料:{context}
这里的 {input} 和 {context} 是变量。
运行时再填进去。
5.2 ChatPromptTemplate
适合聊天型模型。
它可以把消息拆成:
- system
- human
- ai
- history
这个项目里的 Agent 就用了:
ChatPromptTemplateMessagesPlaceholder
意思就是:
把系统提示词、聊天历史、用户输入、Agent 中间思考过程,按聊天消息结构交给模型。
5.3 这个项目里 Prompt 放在哪里
在:
backend/app/prompt/
例如:
main_prompt.txtrag_summarize.txtreorder_prompt.txt
而读取这些 Prompt 的代码在:
backend/app/utils/prompt_loader.py
这个文件做的事情很简单:
- 先读
prompt.yaml - 找到对应 prompt 文件路径
- 把文本内容读出来
这就是“配置化 Prompt”的典型做法。
6. Output Parser:输出解析器
模型返回的往往是文本。
但很多时候我们希望它输出成更明确的结构。
LangChain 里就有 Output Parser 这个概念。
这个项目在 rag_service.py 里用了:
StrOutputParser
它的作用很直接:
把模型输出解析成字符串
虽然看上去简单,但它体现了一个重要思想:
模型输出可以被“接一层处理器”,而不是直接裸用
以后你学更深入时,还会见到:
- JSON 输出解析
- Pydantic 输出解析
- 结构化字段提取
7. Document:文档对象
在 LangChain 里,知识库里的文本通常不是裸字符串,而是 Document 对象。
一个 Document 一般包含:
page_content真实文本内容metadata元数据
7.1 metadata 有什么用
例如你可以在 metadata 里放:
- 文件名
- 文件路径
- 用户 ID
- 页码
- 来源链接
这样后面检索出来时,不只是拿到文本,还知道它从哪来。
这个项目在向量库处理时也会围绕 Document 工作。
8. Embeddings:向量化
Embedding 是 LangChain 里和 RAG 最相关的能力之一。
它的本质是:
把文本变成一组数字,让“语义相似”可以被计算机计算
8.1 为什么要向量化
因为数据库没法直接理解“这两句话意思差不多”。
但如果把它们都映射到向量空间,语义相近的文本就可能距离更近。
于是就能做:
- 语义搜索
- 相似文本匹配
- 文档召回
8.2 这个项目里的 Embedding 流程
在这个项目里:
- 文件被加载
- 文本被切分
- 每个分块生成 embedding
- 写入 Chroma 向量库
- 用户提问时,再把问题转成向量去检索
这条线主要发生在:
backend/app/rag/vector_store.py
9. Vector Store:向量库
LangChain 里可以对接很多向量库,比如:
- Chroma
- FAISS
- Milvus
- Pinecone
- Weaviate
这个项目用的是:
Chroma
9.1 向量库干什么
它主要负责:
- 存储文本向量
- 存储对应文本内容
- 在查询时找最相似的内容
9.2 这个项目里的 Chroma
在 vector_store.py 里有:
Chroma(...)
它会根据配置创建一个向量库实例。
你可以把它理解成:
这个项目的知识库底座
以后无论是上传文件、构建知识库、检索文档,都会围绕它展开。
10. Retriever:检索器
Retriever 是 LangChain 里专门负责“取资料”的组件。
记住一句话:
Retriever 不负责回答,它只负责找相关内容。
10.1 常见检索方式
- 向量检索 适合语义匹配
- BM25 检索 适合关键词匹配
- 混合检索 把多种方式结合起来
10.2 这个项目里的混合检索
vector_store.py 里用了:
BM25Retrieverself.vectors_store.as_retriever(...)EnsembleRetriever
这说明项目并没有只依赖单一检索方式,而是做了融合。
10.3 为什么混合检索更实用
因为真实问题里会同时存在两种情况:
- 有的查询是明确关键词
- 有的查询是自然语言语义表达
混合检索通常更稳。
10.4 动态权重
这个项目还根据 query 的长度和词密度调整检索权重。
这个思路很值得你记住:
RAG 不是只有“查一下”,很多系统都会根据问题类型动态优化检索策略。
11. Text Splitter:文本切分
文本切分虽然容易被忽视,但它非常重要。
因为:
- 文档太长不能整块放进去
- 检索粒度太粗会不准
- 块太短又容易丢上下文
这个项目里有:
backend/app/rag/text_spliter.py
从命名看,它负责异步文本切分。
11.1 为什么切分很重要
同样一份 PDF:
- 切分得太大,检索不精准
- 切分得太小,语义不完整
所以切分策略经常决定 RAG 效果的下限。
项目里也通过配置来控制:
chunk_sizechunk_overlapseparators
这就是典型的工程化做法。
12. Chain:链
Chain 是 LangChain 非常核心的思想。
你可以把它理解成:
把多个步骤串起来,形成一个可执行流程
例如:
- 构造 Prompt
- 调用模型
- 解析输出
这 3 步串起来,就是一个简单的 chain。
12.1 这个项目里的 Chain
在 rag_service.py 里有:
chain = (
self.prompt_template
| self.chat_model
| StrOutputParser()
)
这段是 LangChain 很典型的写法。
意思是:
- 先把输入填进 prompt
- 再交给聊天模型
- 再把输出解析成字符串
这就是一个最小可用链条。
12.2 为什么 Chain 很重要
因为 AI 应用本质上通常不是单步。
它经常是:
- 输入处理
- 检索
- Prompt 拼接
- 模型生成
- 输出清洗
Chain 可以让这些步骤组织得更清楚。
13. Runnable:LangChain 的现代执行风格
虽然你现在不一定需要深究,但看到 | 这种写法时要有概念。
LangChain 现在很多组件都遵循一种“可串联执行”的接口风格。
于是你会看到:
- Prompt 可以接模型
- 模型可以接解析器
- 最后形成一个可执行对象
然后再调用:
invokeainvokestreamastream
13.1 这个项目里常见的是异步调用
因为后端是 FastAPI,很多地方用了:
ainvokeastream
这是很正常的,因为:
- 网络调用适合异步
- 流式返回适合异步
- 并发检索和总结也适合异步
14. Tool:工具
Tool 是 Agent 场景里最关键的组件。
你可以把 Tool 理解成:
暴露给大模型调用的函数
例如:
- 查天气
- 查时间
- 查用户信息
- 检索知识库
- 重排序文档
14.1 这个项目里的工具定义
在:
backend/app/agent/agent_tools.py
里面用到了:
@tool
这个装饰器的意思就是:
把一个 Python 函数包装成 LangChain 可识别的工具
14.2 这个项目里有哪些工具
主要有:
rag_summary_toolsreorder_documents_toolsget_user_info_toolsget_weather_toolswhat_time_is_now
这说明它的 Agent 不只是聊天,而是有“外部能力”的。
14.3 Tool 的本质
你一定要分清:
- Tool 不是模型
- Tool 是模型可调用的函数
模型负责:
- 判断要不要调用
- 传什么参数
Tool 负责:
- 真正执行逻辑
- 把结果返回给模型
15. Agent:智能体
Agent 是 LangChain 里最容易让人兴奋、也最容易让人困惑的部分。
简单说:
Agent 是让模型不仅会回答,还会自己判断是否要调用工具、按什么顺序调用。
15.1 Agent 和普通 Chain 的区别
普通 Chain 通常是固定流程:
输入 -> Prompt -> 模型 -> 输出
Agent 更像动态流程:
输入 -> 模型判断 -> 选工具 -> 调工具 -> 再判断 -> 最终输出
所以:
- Chain 更固定
- Agent 更灵活
15.2 这个项目里的 Agent
核心在:
backend/app/agent/agent.py
这里用了:
create_tool_calling_agentAgentExecutor
大致意思是:
- 创建一个支持工具调用的 Agent
- 再用执行器去跑它
15.3 AgentFactory 的意义
项目里专门写了一个 AgentFactory。
这其实是很好的工程习惯。
它把下面这些东西集中管理:
- 默认模型
- 默认工具
- 默认系统提示词
- 默认中间件
- AgentExecutor 创建逻辑
这样做的好处是:
- 结构清晰
- 可扩展
- 不容易把创建逻辑散落到各处
16. Messages 和 History:聊天历史
LangChain 在聊天场景下,不只是传一个字符串,还会传消息列表。
常见消息类型包括:
- system message
- human message
- ai message
这个项目里在 Agent 执行前,会把数据库中的会话历史转成:
HumanMessageAIMessage
这样模型才能理解:
- 哪些话是用户说的
- 哪些话是助手说的
这就是多轮对话得以成立的关键。
17. Streaming:流式输出
LangChain 支持流式返回。
也就是模型不是等全部生成完再给你,而是一边生成一边输出。
17.1 为什么流式输出重要
因为用户体验会更好:
- 更快看到内容
- 等待感更弱
- 更像 ChatGPT
17.2 这个项目里的流式 Agent
agent.py 里有:
get_agent_stream_response
它内部用:
agent_executor.astream(...)
然后把结果包装成 SSE 风格发回前端。
所以你可以把这一层理解成:
LangChain 负责流式产出 token,FastAPI 负责把它持续推给前端。
18. LangChain 在这个项目里到底扮演什么角色
这是最重要的一段。
如果你要把这个项目和 LangChain 的关系讲明白,可以这样理解:
18.1 LangChain 负责模型抽象
比如:
ChatTongyiOllamaEmbeddings
通过 LangChain 提供统一接口。
18.2 LangChain 负责 Prompt 组织
比如:
PromptTemplateChatPromptTemplateMessagesPlaceholder
18.3 LangChain 负责 RAG 主链路中的关键组件
比如:
DocumentChromaBM25RetrieverEnsembleRetriever
18.4 LangChain 负责 Agent 工具调用机制
比如:
@toolcreate_tool_calling_agentAgentExecutor
18.5 LangChain 负责链式组合
比如:
- Prompt -> Model -> Parser
所以,LangChain 在这个项目里不是“附属功能”,而是整个 AI 层的核心组织框架。
19. 结合这个项目,走一遍 RAG 链路
为了让你更具体感受到 LangChain 的作用,我们走一遍这个项目里的 RAG。
第一步:加载配置和模型
在:
backend/app/utils/config.pybackend/app/utils/factory.py
这里会先准备:
- 聊天模型
- embedding 模型
- 各类配置
第二步:加载文档
在:
backend/app/rag/vector_store.py
项目会读取各种格式的文件,转成文档对象。
第三步:切分和建库
还是在 vector_store.py 中,文档会被切分,然后写入 Chroma。
第四步:创建 Retriever
同一个文件里会创建:
- 向量检索器
- BM25 检索器
- 混合检索器
第五步:RAG 服务发起检索
在:
backend/app/rag/rag_service.py
会调用 retriever 找到相关文档。
第六步:构造 Prompt + 调模型
同样在 rag_service.py 里:
- 把 query 和 context 放入 PromptTemplate
- 调聊天模型
- 再交给
StrOutputParser
第七步:返回摘要答案
最终形成给前端或接口层使用的结果。
这整条线如果没有 LangChain,代码会散很多。
20. 再走一遍 Agent 链路
第一步:定义工具
在:
backend/app/agent/agent_tools.py
把 Python 函数用 @tool 注册。
第二步:创建 Agent Prompt
在:
backend/app/agent/agent.py
通过 ChatPromptTemplate.from_messages(...) 组织:
- system prompt
- 聊天历史
- 用户输入
- agent scratchpad
第三步:创建 Tool Calling Agent
也是在 agent.py:
create_tool_calling_agent(...)
这表示模型具备调用工具的能力。
第四步:用 AgentExecutor 执行
执行器负责:
- 驱动整个 Agent 运行
- 处理工具调用循环
- 输出最终结果
第五步:记录中间步骤
项目里还把:
- thought
- tool
- tool_input
- tool_output
都记录下来。
这对调试 Agent 很重要。
21. 为什么这个项目没有把所有逻辑都写死,而是用了 LangChain
因为这个项目明显已经不是“只发一句 prompt 给模型”的简单 demo。
它有这些需求:
- 要支持多轮对话
- 要支持文档知识库
- 要支持混合检索
- 要支持重排序
- 要支持工具调用
- 要支持流式输出
这种复杂度下,LangChain 的价值就很明显:
- 减少重复造轮子
- 统一抽象
- 便于组合扩展
22. 初学 LangChain 时最容易踩的坑
22.1 把 LangChain 当成模型
错。
LangChain 是框架,不是模型本身。
22.2 以为用了 LangChain 效果就一定好
也错。
LangChain 只是让你更容易搭系统,不保证效果自动变好。
真正影响效果的仍然包括:
- 模型能力
- prompt 设计
- 检索策略
- 文档质量
- 切分方式
- rerank 质量
22.3 一上来就学 Agent
这也是常见误区。
更合理的顺序应该是:
- 先学 Prompt
- 再学 Model
- 再学 Chain
- 再学 RAG
- 最后学 Agent
因为 Agent 是建立在前面这些概念之上的。
23. 你应该怎么学这个项目里的 LangChain
给你一个最适合初学者的阅读顺序:
第一层:先看“模型和配置”
看:
backend/app/utils/config.pybackend/app/utils/factory.pybackend/app/utils/prompt_loader.py
搞懂:
- 模型从哪来
- 配置从哪来
- prompt 从哪来
第二层:看 RAG
看:
backend/app/rag/vector_store.pybackend/app/rag/rag_service.py
搞懂:
- 文档怎么处理
- 向量库怎么用
- 检索怎么做
- 最终回答怎么生成
第三层:看 Agent
看:
backend/app/agent/agent_tools.pybackend/app/agent/agent.py
搞懂:
- 工具怎么定义
- Agent 怎么创建
- 执行器怎么跑
- 流式怎么实现
第四层:回到路由层
看:
backend/app/router/chat.py
搞懂:
- 这些 AI 能力最终是怎么通过 API 暴露出去的
24. 一张图总结 LangChain 在这个项目中的位置
flowchart TD
A["前端请求"] --> B["FastAPI 路由"]
B --> C["LangChain RAG 流程"]
B --> D["LangChain Agent 流程"]
C --> C1["PromptTemplate"]
C --> C2["Embedding Model"]
C --> C3["Chroma Vector Store"]
C --> C4["Retriever"]
C --> C5["Chat Model"]
C --> C6["Output Parser"]
D --> D1["ChatPromptTemplate"]
D --> D2["@tool 工具"]
D --> D3["Tool Calling Agent"]
D --> D4["AgentExecutor"]
D --> D5["Streaming 输出"]
25. 最后做个一句话总结
如果你以后要向别人解释 LangChain,可以直接说:
LangChain 不是大模型,而是一个帮助我们把模型、Prompt、知识库、检索、工具和 Agent 串起来的开发框架。在这个项目里,它既支撑了 RAG 文档问答,也支撑了 Agent 的多工具调用能力,是整个 AI 后端的核心组织层。
如果你愿意,我下一步可以继续帮你把这篇再升级成:
- “更适合面试复述”的精简版
- “每个 LangChain 类都对应到项目源码位置”的对照版