小白程序员轻松上手大模型:LangChain核心组件详解与实战
本文从简单的OpenAI调用入手,逐步展示随着需求增加,代码维护的复杂性如何提升。引入LangChain框架,通过Model I/O、Retrievers、Chains、Agents和Memory五个核心组件,标准化并简化了模型调用、知识检索、流程编排和多轮对话管理。最后,通过一个最小可运行的RAG示例,展示了如何使用LangChain构建高效的大模型应用,并探讨了LangChain的使用场景和边界。
一、先看最原始的写法:调一次 OpenAI
假设你现在要写一个「能查公司内部文档的客服机器人」。最简单的起步是:直接调 OpenAI 的 Chat Completions 接口,把用户问题和相关文档拼成一段 prompt,送过去拿回答案。
下面这段代码,可能是你第一天上班写出来的样子:
import requests
def ask_bot(user_question, context_docs): prompt = f"""你是客服机器人,根据下面上下文回答用户问题。上下文:{context_docs}用户问题:{user_question}答案:""" response = requests.post( "https://api.openai.com/v1/chat/completions", headers={"Authorization": f"Bearer {API_KEY}"}, json={ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": prompt}], "temperature": 0, }, ) return response.json()["choices"][0]["message"]["content"]
这段代码能跑、能交付。用户问「报销标准」,你把员工手册的相关段落拼进 context_docs,函数返回答案。看起来没什么问题。
二、每加一个需求就改一次代码,问题开始暴露
产品第二天来说:「机器人要从内部知识库检索相关文档,不要人工挑文档传进来。」
你要做的事:加一步检索——把用户问题转成向量,去向量库里找最相似的几段文档,再把这几段拼进 prompt。于是代码变成:
def ask_bot_with_retrieval(user_question): # 新加的检索步骤 query_vec = embed(user_question) similar_chunks = vector_db.search(query_vec, top_k=3) context_docs = "/n".join(c.text for c in similar_chunks) prompt = f"""你是客服机器人,根据下面上下文回答用户问题。上下文:{context_docs}用户问题:{user_question}答案:"""
# 调用模型的代码和上面一模一样 response = requests.post(...) return response.json()["choices"][0]["message"]["content"]
产品第三天来说:「换成 Anthropic 的 Claude 做对比测试,看下两家模型谁的回答更好。」
你要做的事:重新写一套 Anthropic 的 HTTP 调用逻辑(URL、请求体结构、响应结构都不一样),外层还得加个分支判断走哪条路径。之前那段 requests.post(…) 的代码整段要重写。
产品第四天来说:「加多轮对话记忆,用户能连续追问。」
你要做的事:在函数外面维护一个 history 列表,把每一轮的 user 与 assistant 消息都存起来,每次拼 prompt 时把 history 也塞进去。prompt 模板又改了一遍。
history = []
def ask_bot_multi_turn(user_question): # 维护对话历史 history.append({"role": "user", "content": user_question}) prompt = build_prompt_with_history(history, context_docs) response = requests.post(...) answer = response.json()["choices"][0]["message"]["content"] history.append({"role": "assistant", "content": answer}) return answer
走到这里,代码还能跑,但你已经开始意识到一件事:每加一个需求,你都要把之前写好的代码改一大块。加检索要改 prompt 构造的代码,换模型要改模型调用的代码,加记忆又要改 prompt 构造的代码。如果以后还要把「检索 → 模型调用 → 解析输出 → 再检索」串成一个更长的流程,代码会变成一坨难以维护的函数堆叠。
这不是你的代码能力问题,是这种写法的结构问题:业务逻辑(要回答什么问题)和底层实现(调哪个模型、怎么检索、怎么保存历史)耦合在一起。耦合导致的重复,每加一个需求就要重做一遍。
三、LangChain 在这一步出现
LangChain 由 Harrison Chase 在 2022 年 10 月开源。它解决的正是上面暴露的问题:把「调模型、做检索、串流程、保存历史」这些共性工作抽出来,做成独立的组件。你换模型时只换模型组件,加检索时只加检索组件,业务代码不用动。
理解这一点非常重要:LangChain 不是一个模型,也不是一个闭源平台。它本身不提供 LLM 能力(LLM 由 OpenAI / Anthropic / 本地 Ollama 提供),不提供向量库(由 Milvus / Qdrant / FAISS 提供),不提供工具(由具体 API 提供方提供)。它是一个集成框架,把所有外部能力的调用方式统一起来,让你用同一套接口接入不同的 LLM、不同的向量库、不同的工具。
具体来说,LangChain 给你的是一层统一的调用协议:不管背后接的是 OpenAI 还是 Anthropic,你写的代码都是 llm.invoke(messages);不管向量库是 FAISS 还是 Milvus,你写的都是 retriever.invoke(query)。这层协议的代价是多一层抽象需要理解,收益是换底层时只改配置不改业务。
定位摆正之后,五个组件各自解决什么问题就很好理解了——每个组件对应你上面手工写过的一段胶水代码。

四、Model I/O:把「调模型」这段标准化
上面你手工写的 requests.post(…) 那段代码,在做三件事:拼 prompt、调模型、从响应 JSON 里取出答案文本。LangChain 把这三件事拆成三段:
- PromptTemplate:拼 prompt 的模板,把
{user_question}与{context_docs}这种变量填到固定文案里。 - ChatModel:调模型的统一接口,背后接 OpenAI 就是 ChatOpenAI,接 Anthropic 就是 ChatAnthropic,接本地 Ollama 就是 ChatOllama。换模型只换这个对象,外层代码不动。
- OutputParser:把模型输出的文本解析成下游能直接用的结构化数据(JSON、字典、Pydantic 对象)。
把上面那段代码用 Model I/O 重写,长这样:
from langchain_openai import ChatOpenAIfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParser prompt = ChatPromptTemplate.from_template( ”你是客服机器人,根据上下文回答。/n上下文:{context}/n问题:{question}/n答案:”)llm = ChatOpenAI(model=”gpt-4o-mini”, temperature=0)output_parser = StrOutputParser()
三段分开定义,彼此独立。换模型只换 ChatOpenAI 那一行变成 ChatAnthropic,prompt 模板不动、解析器不动、外层业务也不动。这就是抽象带来的解耦。
五、Retrievers:把「查外部知识」这段标准化
你手工写的 embed(user_question) 与 vector_db.search(…) 这两步,LangChain 用一个 Retrievers 组件封装起来。Retrievers 的接口非常简单:给一个 query,返回一组 Document(每个 Document 含 page_content 正文与 metadata 来源信息)。
最常见实现是VectorStoreRetriever:底层接一个 VectorStore(FAISS、Milvus、Qdrant 等),query 先过 Embedding 模型转向量,再算与库中向量的相似度,取最相似的 K 个 Document 返回。
from langchain_community.vectorstores import FAISSfrom langchain_openai import OpenAIEmbeddingsembeddings = OpenAIEmbeddings(model="text-embedding-3-small")vectorstore = FAISS.from_documents(docs, embeddings)retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 业务代码只看到这一行results = retriever.invoke("报销标准是多少")
这一步被标准化之后,你换向量库、换 Embedding 模型,外层调用都不用改——业务代码只看到一个 retriever.invoke(query),背后接什么库由配置决定。
六、Chains:把「多步流程」串起来
上面你的流程是「检索 → 拼 prompt → 调模型 → 解析输出」四步。没有 LangChain 时,你要用函数嵌套来串:
def rag_pipeline(question): # 第一步:检索 docs = retriever.search(question) context = "/n".join(d.text for d in docs) # 第二步:拼 prompt prompt = build_prompt(context, question) # 第三步:调模型 raw = call_openai(prompt) # 第四步:解析输出 return parse_answer(raw)
这段代码能跑,但每加一步(比如加一个 Rerank、加一个输出格式化)就要改函数内部。而且整个流程只能一次性调用,不支持流式输出、不支持批量、不支持异步——你要每种模式都手写一套。
LangChain 用 Chains 把这些步骤串成一条链。在 LCEL 写法里,所有组件都是 Runnable,用 | 运算符连接,前一步的输出自动成为后一步的输入:
chain = retriever | format_docs | prompt | llm | output_parseranswer = chain.invoke(”报销标准是多少”)
这条链对外也是一个 Runnable——你可以 chain.invoke() 单次调用、chain.batch() 批量调用、chain.stream() 流式输出、chain.ainvoke() 异步调用,四种模式不用改一行代码。这是 Chains 的核心特征:确定性加统一接口。每一步做什么、顺序如何,在写代码时就固定了;但调用方式统一,不必为流式或异步重写逻辑。
七、Memory:让多轮对话能延续
你手工写的那个 history 列表,每次手动 append、手动拼进 prompt,LangChain 用 Memory 组件把这件事标准化。
没有 LangChain 时,你要自己管理对话状态:
history = []def chat(question): history.append({"role": "user", "content": question}) messages = history[-10:] # 只取最近 10 轮,不然 token 爆掉 answer = call_openai(messages) history.append({"role": "assistant", "content": answer}) return answer
这段代码有两个问题:窗口大小要你自己管([-10:] 硬编码),持久化要你自己写(进程一重启,history 全丢)。
LangChain 提供两类 Memory 来解决这两个问题。短期记忆(如 ConversationBufferWindowMemory)把最近 K 轮保存在内存里,K 值可配置;长期记忆(如 VectorStoreMemory)把对话摘要或关键事实持久化到外部存储,跨会话可用。Memory 组件接入 Chain 后,你不用手动维护 history 列表,LangChain 在每次调用时自动把历史消息注入 prompt。
Memory 是可选的:单轮问答不需要 Memory,把它当标配会让简单场景变复杂。只在你的应用需要多轮连续对话时才引入。
八、Agents:让流程可以由 LLM 动态决定
如果你的机器人要面对更复杂的场景——用户问的问题可能要查多个数据源、可能要调工具、可能要推理多步——固定流程的 Chain 就不够用。LangChain 用 Agents 解决这类问题:让 LLM 在运行时决定下一步做什么。
经典的ReAct模式(Reasoning → Action → Observation → 再 Reasoning)就是 Agent 的典型实现。用一个具体例子来说明:假设用户问「北京今天的气温比上海高几度」,Chain 处理不了,因为这条流程不是固定的——要先调天气 API 查北京气温、再查上海气温、再做减法。Agent 的处理方式是这样:
思考(Thought):我需要先查北京的当前气温行动(Action):调用 weather_api(”北京”)观察(Observation):28°C思考:还需要查上海的气温行动:调用 weather_api(”上海”)观察:22°C思考:28 - 22 = 6,可以回答了最终答案:北京今天比上海高 6 度
每一轮 LLM 先思考该做什么、然后调用一个工具、观察工具返回、再进入下一轮思考,直到 LLM 判断可以给出最终答案为止。工具的注册与调用由 LangChain 统一管理——你只需要声明「这个 Agent 可以用哪些工具」,LLM 自己决定什么时候调哪个。
Chain 与 Agent 的根本区别是:Chain 是写代码时确定的流程,Agent 是运行时由 LLM 决定的流程。Agent 更灵活,但也更不可预测、更难调试——所以在生产环境里,很多人倾向于用 LangGraph 把 Agent 的状态机写得更可控,这是后面第 6 篇的主题。
九、把五组件串成一个最小可运行的 RAG
回到开头那个客服机器人。下面这段代码用 LangChain 写出来,五个组件全部出现。先看数据流全景:

再看对应代码:
from langchain_openai import ChatOpenAI, OpenAIEmbeddingsfrom langchain_community.vectorstores import FAISSfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.runnables import RunnablePassthroughfrom langchain_core.documents import Document
# Model I/O 三段llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)prompt = ChatPromptTemplate.from_template( "根据上下文回答:/n{context}/n问题:{question}/n答案:")output_parser = StrOutputParser()
# Retrievers:接 FAISS(生产环境换 Milvus / Qdrant)embeddings = OpenAIEmbeddings(model="text-embedding-3-small")docs = [ Document(page_content="报销标准:国内住宿 500 元/晚"), Document(page_content="差旅申请需提前 3 天提交"),]vectorstore = FAISS.from_documents(docs, embeddings)retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# Chains:用 LCEL 的 | 运算符串成一条链def format_docs(docs): return "/n".join(d.page_content for d in docs)chain = ( {"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | output_parser)
# 调用answer = chain.invoke("出差住宿标准是多少?")print(answer)
代码里五个组件各出现一次:ChatOpenAI、ChatPromptTemplate、StrOutputParser 是 Model I/O 三段;FAISS + Embeddings + as_retriever 合起来是 Retrievers;整条 chain 是 Chains。Memory 与 Agents 没出现,因为这是单轮问答、流程固定。
LCEL(LangChain Expression Language)是这套写法的名字:所有组件都实现同一个 Runnable 接口,用 | 运算符串成链。它让组合方式统一——无论接入 LLM、Retriever 还是 Tool,调用方式都一样,流式与异步也自动支持。LCEL 是 LangChain 区别于其他框架的关键设计,第 2 篇会专门展开。
十、实践里的取舍:LangChain 什么时候用、什么时候不用
写到这一步,要诚实地讲一下 LangChain 的边界。
简单场景不需要 LangChain。如果你的项目只是调一次 LLM 拿结果,直接用 OpenAI SDK 就够了。LangChain 的抽象层在这类场景里是心智成本,不是便利。
流程固定且不复杂时,手写函数也可以。LangChain 的价值在多组件组合、要换底层、要做多轮对话、要编排 Agent 这些场景里才显现出来。如果你的项目只有两三个固定场景,手写可能更快。
LangChain 的抽象层较多,调试时不如裸代码直观。遇到 bug 时要穿过 Runnable、Chain、PromptTemplate 多层去看,对新手不友好。重度项目里很多人会退回到「直接用 LCEL + LangGraph」的写法,绕过上层 Agent 抽象。
升级底层 LLM 的收益,往往大于优化 LangChain 代码。LangChain 的所有能力都依赖外部提供方,换更强的模型、调更好的切块策略、换更合适的 Embedding,效果提升通常比调整 LangChain 代码更明显。
一句话:LangChain 做的是减法——让你少写重复的胶水代码——不是加法,它不会让你的系统多出什么独有能力。
如果你需要一个简单的判断标准:项目里只有一个 LLM 调用、不换底层、不做多轮,不必引入 LangChain;项目里要组合检索与生成、可能换模型、需要多轮或 Agent,LangChain 能帮你省掉大量重复代码。
十一、小结
这一篇按「从零到一」的路径走了一遍:
-
先写最原始的代码,调一次 OpenAI 拿结果。
-
加检索、换模型、加记忆,每加一个需求就改一次代码,暴露出「业务与底层耦合」的问题。
-
LangChain 把这一层抽出来,做成五个组件:Model I/O(调模型)、Retrievers(检索)、Chains(串固定流程)、Agents(让 LLM 决定流程)、Memory(多轮对话状态)。
-
用一段最小可运行的 RAG 代码把五个组件串起来。
-
讲清楚 LangChain 的定位(集成框架,不提供模型)和边界(简单场景不必用)。
下一篇讲 LCEL 的实现细节:Runnable 协议、| 运算符、invoke / batch / stream / ainvoke 四种运行模式、Callbacks、并行与重试。把 LCEL 讲透之后,你就能读懂 LangChain 文档里所有用 | 串起来的代码了。
本篇核心术语表
| 术语 | 解释 |
|---|---|
| Model I/O | LangChain 把「调模型」拆成的三段标准组件:PromptTemplate(拼 prompt)、ChatModel(调模型)、OutputParser(解析输出) |
| Retrievers | 检索组件的统一接口,给一个 query 返回一组 Document,最常见实现是 VectorStoreRetriever |
| Chains | 把多个步骤串成一条固定流程的编排组件,所有步骤在写代码时确定 |
| Agents | 让 LLM 在运行时动态决定下一步做什么的编排组件,典型模式为 ReAct |
| Memory | 管理多轮对话状态的组件,分短期(内存窗口)与长期(外部存储持久化)两类 |
| LCEL | LangChain Expression Language,所有组件实现 Runnable 接口后用竖线运算符串链的统一写法 |
| Runnable | LangChain 的统一协议,定义了 invoke、batch、stream、ainvoke 四种调用模式 |
| ReAct | Reasoning + Action 循环模式,Agent 的经典实现:思考、调工具、观察、再思考 |
。
大模型的知识又多又杂,到底怎么学?
做这行久了,被问最多的问题就一个:大模型的知识又多又杂,我到底先学啥?翻了一堆资料,看啥都像重点,结果啥都没学进去。今天把我自己一路摸出来的顺序捋一遍,零基础、应届生、转行的都适用。跟着走,至少方向不乱、不瞎忙,学完拿得出手。
第一阶段(10天):初阶应用
这一阶段就一个目标:把大模型真正"玩明白",不是只会聊天那种,而是能调教它、能用代码把大模型和业务接起来。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
这阶段正式进实战,目标很实在:做出两个能拿出手的东西——一个私有知识库,一个 agent 对话机器人。
-
为什么要做 RAG
-
搭建一个简单的 ChatPDF
-
检索的基础概念
-
什么是向量表示(Embeddings)
-
向量数据库与向量检索
-
基于向量检索的 RAG
-
搭建 RAG 系统的扩展知识
-
混合检索与 RAG-Fusion 简介
-
向量模型本地部署
-
…
走完这 30 天,Python 或 JavaScript 背景的基本能独立做一套 RAG 应用,简历上也敢写"大模型应用开发"了。
第三阶段(约20天):动手微调
学到这,你已经开始 “造” 模型了 —— 通过微调,搞出垂直领域的专用小模型。
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你从 “只会用” 变成 “能造” 的 AI 小子。那么你还想往下探索吗?
想要入局AI大模型赛道、抢占行业红利的朋友,微信扫描下方CSDN官方认证二维码,即可100%免费领取全套学习资料!
第四阶段(20天):商业闭环,部署落地
技术学完,落地才算数。这阶段带你搞明白大模型怎么真正跑起来、用起来。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
想要入坑大模型的朋友,给大家准备了一份2026 年最新 AI 大模型全套学习资料:
1、大模型系统化学习路线

2、大模型学习视频教程

3、大模型学习书籍&电子文档

4、AI大模型最新行业报告

5、大模型项目实战&配套源码

6、2026大模型大厂面试真题

7、为什么要学习大模型?
我国在A大模型领域面临人才短缺,数量与质量均落后于发达国家。2023年,人才缺口已超百万,凸显培养不足。随着AI技术飞速发展,预计到2025年,这一缺口将急剧扩大至400万,严重制约我国AI产业的创新步伐。加强人才培养,优化教育体系,国际合作并进是破解困局、推动AI发展的关键。


8、适合谁学?
- 传统后端 / Java / 前端开发,想转型 AI 应用
- 大学生、应届生,想拿更好的 offer
- 产品经理、运营,想武装职业竞争力
- 技术负责人,想给团队落地提效
学习是反人性的,但回报是真金白银。技术会更新,赛道会切换,但只要你先动手,机会就永远站在你这边。
9、这些资料真的有用吗?
这份资料由我和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理,现任上海殷泊信息科技CEO,其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证,服务航天科工、国家电网等1000+企业,以第一作者在IEEE Transactions发表论文50+篇,获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。
资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。
想要入局AI大模型赛道、抢占行业红利的朋友,微信扫描下方CSDN官方认证二维码,即可100%免费领取全套学习资料!
好了,就写到这。路线是死的,人是活的,卡住了随时来问我。觉得有用就点个收藏,别让它进收藏夹吃灰——动起来比啥都强。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)