news 2026/9/23 4:55:38

从API调用到Agent开发:LangChain、RAG与LangGraph实战学习路线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从API调用到Agent开发:LangChain、RAG与LangGraph实战学习路线

1. 从“会用”到“会造”:大模型应用开发的学习路径拆解

我真正开始系统学习大模型应用开发,是在把聊天窗口里那些“哇,好神奇”的新鲜感消耗完之后。那时候我发现一个很尴尬的事实:我能跟大模型聊得火热,却没法把它变成一个能解决具体问题的产品。问它问题它答得头头是道,但让它去查我本地的文档、调用我的接口、记住我上一轮说过的话,它就立刻露馅。这个落差,就是我从“大模型使用者”转向“大模型应用开发者”的起点。

如果你也处在这个阶段——能调用API,但不知道怎么把大模型串进一个完整的业务流里;听说过LangChain、LangGraph、RAG这些词,但不知道它们各自解决什么问题、什么时候该用哪个;想做一个属于自己的知识库问答或者Agent项目,却卡在环境配置和框架选型上——那这篇内容就是写给你的。我会把我自己踩过的路、绕过的弯、以及最后沉淀下来的学习顺序和实操方法,完整地摊开来讲。核心关键词就几个:大模型、Agent、LangChain、LangGraph、RAG,但我会把它们放在真实的开发场景里讲,而不是干巴巴地念概念。

先说一个我自己的判断:大模型应用开发这件事,门槛不在“模型”本身,而在“应用”这两个字。模型是别人训练好的,你改不了底层参数(除非做微调,那是另一条路),你能控制的是怎么给它喂上下文、怎么让它调用工具、怎么管理它的记忆、怎么把它的输出变成结构化数据。这四件事,分别对应了RAG、Agent、LangGraph和输出解析。把这四块吃透,你就能从“调API的人”变成“做应用的人”。

我给自己定的学习路线是这样的:先用LangChain把最基础的链式调用跑通,理解Prompt、Model、OutputParser这三件套;然后立刻上手RAG,因为这是最容易看到效果、也最贴近实际需求的方向;接着学Agent,让模型学会自己决定调用什么工具;最后用LangGraph把前面这些零散的能力编排成一个有状态、可循环、能处理复杂分支的完整工作流。这个顺序不是拍脑袋定的,而是按照“依赖关系”来的——没有RAG和Agent的基础,直接上LangGraph会非常痛苦,因为你不知道每个节点里该放什么。

提示:不要一上来就追求“全栈大模型工程师”的标签。先把一条链路跑通,哪怕只是“读取本地PDF→切分→向量化→检索→生成回答”这么简单的RAG,跑通一遍胜过看十篇综述。

2. 核心概念拆解:LangChain、LangGraph、RAG、Agent到底怎么分工

2.1 LangChain:不是框架,是“胶水层”

很多人对LangChain的第一印象是“太重了”“抽象太多”。我一开始也这么觉得,尤其是看官方文档的时候,各种Chain、Runnable、Tool、Memory的概念扑面而来,很容易劝退。但后来我想明白了一件事:LangChain的本质不是让你写更少的代码,而是给你一套统一的接口,让你能把不同厂商的模型、不同的向量数据库、不同的工具用同一种方式串起来。

举个例子,你今天用OpenAI的模型,明天想换成Ollama本地部署的模型,如果没有LangChain,你得把代码里所有调用模型的地方都改一遍。但用了LangChain之后,你只需要换一个ChatOpenAIChatOllama,其他代码基本不动。这就是“胶水层”的价值——它不生产能力,它只是能力的搬运工。

我学LangChain的方法是“用多少学多少”,而不是从头到尾读文档。具体来说,我先跑通一个最简单的链:

from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser prompt = ChatPromptTemplate.from_template("用一句话解释{concept}") model = ChatOpenAI(model="gpt-4o-mini") parser = StrOutputParser() chain = prompt | model | parser print(chain.invoke({"concept": "RAG"}))

这段代码虽然简单,但它包含了LangChain最核心的表达式语言(LCEL)思想:用管道符|把各个组件串起来。你理解了这一行,就理解了LangChain一半的设计哲学。剩下的Memory、Tool、Retriever,都是在这个基础上往外扩。

2.2 RAG:给大模型装上“外挂知识库”

RAG是我认为最值得优先投入时间的方向,因为它解决的是大模型最致命的两个问题:知识过时和幻觉。你问大模型一个关于你公司内部文档的问题,它要么不知道,要么一本正经地胡说八道。RAG的思路很直接:既然模型不知道,那我就把相关资料找出来,塞进Prompt里让它基于资料回答。

RAG的完整链路包括:文档加载→文本切分→向量化→存储→检索→重排→生成。每一步都有坑。比如文本切分,你切得太碎,语义不完整;切得太大,检索精度下降。我自己的经验是,中文文档用RecursiveCharacterTextSplitter,chunk_size设在500到800之间,chunk_overlap设在50到100之间,这个范围在大多数场景下比较稳。

向量化模型的选择也很关键。如果你做的是中文RAG,不要直接用OpenAI的text-embedding-ada-002,它在中文上的表现只能说凑合。可以考虑BGE系列或者M3E,这些在中文语义相似度任务上表现更好。如果你要本地部署,Ollama里可以拉nomic-embed-text或者bge-m3,配合Chroma或者FAISS做本地知识库,整套流程可以完全离线跑。

注意:RAG不是“向量检索”的同义词。完整的RAG还包括检索后的重排(Rerank)和生成时的Prompt约束。只做向量检索不做重排,召回的相关文档可能排在后面,导致模型看不到关键信息。

2.3 Agent:让模型自己决定“下一步做什么”

Agent和普通链式调用的区别,我用一个类比来解释:普通链就像流水线,每一步都是你提前定好的,第一步做完做第二步,第二步做完做第三步。Agent则像一个有自主权的员工,你给它一个目标,它自己决定先做什么、再做什么、要不要调用工具、调用哪个工具。

LangChain里的Agent核心是“工具调用”机制。你定义几个工具(比如搜索、计算器、查数据库),然后让模型根据用户的问题自己选择调用哪个。这个过程是循环的:模型思考→选择工具→执行工具→观察结果→继续思考,直到它认为可以给出最终答案。

我踩过的一个坑是:一开始给Agent定义了太多工具,结果模型经常选错。后来我学乖了,工具数量控制在5个以内,每个工具的description写得非常明确,说明“什么时候该用这个工具”,而不是只写“这个工具是干什么的”。比如不要写“查询天气”,而要写“当用户询问某个城市的实时天气、温度、降水概率时使用此工具”。

2.4 LangGraph:把Agent的“思考过程”画成图

LangGraph是我认为最被低估的一个工具。很多人觉得LangChain已经够用了,为什么还要学LangGraph?我的回答是:当你需要循环、分支、状态共享、人工介入的时候,LangChain的链式结构就不够用了。

LangGraph把工作流建模成一张图,节点是函数,边是流转条件。你可以定义条件边,让流程根据当前状态决定下一步走哪个节点。这听起来很抽象,但实际用起来非常自然。比如做一个客服Agent,用户问题先分类,如果是退款就走退款流程,如果是咨询就走咨询流程,如果分类置信度低就转人工。这种逻辑用LangGraph表达非常清晰。

LangGraph和LangChain的关系,我的理解是:LangChain提供了组件(模型、工具、检索器),LangGraph提供了编排这些组件的方式。你可以把LangGraph看作LangChain的上层建筑,它不替代LangChain,而是让LangChain的组件在更复杂的场景下协同工作。

维度LangChainLangGraph
核心抽象Chain / RunnableStateGraph / Node / Edge
流程控制线性为主,支持简单分支支持循环、条件分支、并行
状态管理通过Memory传递显式定义State,全局共享
适用场景简单链式调用、RAG复杂Agent、多轮决策、人工介入
学习曲线较平缓需要理解图论基础概念

3. 实操环境搭建:从零把开发环境跑起来

3.1 Python环境与依赖管理

我强烈建议用Conda来管理大模型应用开发的Python环境,不要用系统自带的Python。原因很简单:大模型相关的库更新极快,依赖冲突是家常便饭。Conda可以给每个项目建独立环境,互不干扰。

conda create -n llm-dev python=3.11 conda activate llm-dev pip install langchain langchain-openai langchain-community pip install chromadb faiss-cpu pip install langgraph pip install streamlit

Python版本选3.11而不是3.12,是因为有些向量数据库的底层库对3.12的支持还不完善。这个坑我踩过,装FAISS的时候编译报错,换回3.11就顺利了。

3.2 模型接入:云端API与本地部署的取舍

学习阶段我建议先用云端API,因为便宜、稳定、不用折腾硬件。OpenAI的gpt-4o-mini性价比很高,适合练手。但如果你对数据隐私有要求,或者想完全离线运行,那就需要本地部署。

本地部署大模型,目前最省心的方案是Ollama。它把模型下载、量化、推理服务都封装好了,你只需要一行命令:

ollama pull qwen2.5:7b ollama pull nomic-embed-text

然后LangChain里这样接:

from langchain_ollama import ChatOllama, OllamaEmbeddings model = ChatOllama(model="qwen2.5:7b", temperature=0) embeddings = OllamaEmbeddings(model="nomic-embed-text")

选哪个本地模型?我的经验是:7B参数级别的模型,Qwen2.5在中文任务上表现很稳,适合做RAG的生成模型。嵌入模型用nomic-embed-text或者bge-m3,后者对中文更友好。如果你的显卡显存只有8GB,7B模型用4-bit量化可以跑,但速度会慢一些。显存12GB以上可以考虑14B模型,效果明显更好。

提示:本地部署的模型在指令遵循能力上通常不如云端大模型。做Agent的时候,如果发现模型不按格式输出工具调用,先换云端模型验证逻辑,再回来调本地模型的Prompt。

3.3 向量数据库选型:Chroma vs FAISS

学习阶段我推荐Chroma,因为它自带持久化、API简单、和LangChain集成度高。FAISS性能更好,但它是纯索引库,不负责文档存储,你需要自己管理文档和元数据。

from langchain_chroma import Chroma vectorstore = Chroma.from_documents( documents=chunks, embedding=embeddings, persist_directory="./chroma_db" ) retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

k=4是我常用的检索数量。太小可能漏掉关键信息,太大则噪音多、消耗Token。你可以根据文档的粒度调整,如果chunk比较小,可以设到6到8。

4. RAG实战:从文档到可问答的知识库

4.1 文档加载与切分策略

RAG的第一步是把你的资料变成模型能消化的文本块。LangChain提供了大量DocumentLoader,PDF用PyPDFLoader,Word用Docx2txtLoader,网页用WebBaseLoader。但我要提醒一句:PDF解析是RAG里最脏最累的活。扫描版PDF需要OCR,表格多的PDF解析出来格式全乱,这些都会直接影响后续检索质量。

切分策略上,我试过固定长度切分、按段落切分、按语义切分。最后发现最稳的还是RecursiveCharacterTextSplitter,它按照分隔符优先级递归切分,尽量保持语义完整。

from langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=600, chunk_overlap=80, separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""] ) chunks = splitter.split_documents(docs)

注意separators里我把中文标点加进去了,因为默认的分隔符只考虑英文标点,对中文文档不友好。这个细节很多教程不会讲,但实际做中文RAG的时候非常关键。

4.2 检索优化:混合检索与重排

单纯的向量检索有个问题:它对关键词匹配不敏感。比如用户问“RX6750GRE能跑大模型吗”,向量检索可能返回一堆关于“显卡跑大模型”的通用文档,但漏掉具体提到这个型号的文档。解决办法是混合检索:向量检索加BM25关键词检索,两路召回后合并去重。

LangChain里可以用EnsembleRetriever来实现:

from langchain.retrievers import EnsembleRetriever, BM25Retriever bm25_retriever = BM25Retriever.from_documents(chunks) bm25_retriever.k = 4 vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 4}) ensemble = EnsembleRetriever( retrievers=[bm25_retriever, vector_retriever], weights=[0.4, 0.6] )

权重分配上,我一般让向量检索占6成,BM25占4成。如果你的文档里专有名词多,可以调高BM25的权重。

检索之后如果还想再提精度,可以加一个重排模型。重排模型(Reranker)会对召回的文档做精细打分,把最相关的排到最前面。常用的有bge-reranker系列,可以用FlagEmbedding或者sentence-transformers加载。这一步会增加延迟,但对精度提升明显,尤其是召回文档多的时候。

4.3 Prompt模板与幻觉抑制

RAG的生成环节,Prompt写得好不好直接决定回答质量。我的模板是这样的:

RAG_PROMPT = """你是一个严谨的问答助手。请仅根据以下参考资料回答用户问题。 如果参考资料中没有相关信息,请直接说“根据现有资料无法回答”,不要编造。 参考资料: {context} 用户问题:{question} 回答要求: 1. 只使用参考资料中的信息 2. 如果资料中有矛盾,指出矛盾 3. 回答要简洁,不要重复问题 """

这个模板里最关键的是“如果资料中没有相关信息,请直接说无法回答”。不加这句话,模型会倾向于用它的预训练知识来补全,导致幻觉。加了之后,虽然有时候会显得“笨”,但可靠性大幅提升。

5. Agent与LangGraph:从单步调用到复杂工作流

5.1 用LangChain构建第一个Agent

Agent的核心是工具调用。我先定义一个简单的工具集:

from langchain_core.tools import tool @tool def search_knowledge_base(query: str) -> str: """当用户询问产品文档、技术手册相关问题时使用此工具。输入应该是完整的问题描述。""" docs = retriever.invoke(query) return "\n\n".join([d.page_content for d in docs]) @tool def calculate(expression: str) -> str: """当用户需要进行数学计算时使用此工具。输入应该是合法的Python数学表达式。""" return str(eval(expression))

然后创建Agent:

from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个乐于助人的助手,可以调用工具来回答问题。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}") ]) agent = create_tool_calling_agent(model, [search_knowledge_base, calculate], prompt) executor = AgentExecutor(agent=agent, tools=[search_knowledge_base, calculate], verbose=True)

verbose=True在学习阶段非常有用,它会把Agent的思考过程和工具调用完整打印出来,你能清楚看到模型为什么选这个工具、传了什么参数。

5.2 LangGraph入门:把流程画成图

LangGraph的核心概念是StateGraph。你先定义状态的结构,然后添加节点和边。

from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated from langgraph.graph.message import add_messages class State(TypedDict): messages: Annotated[list, add_messages] route: str def classify(state: State): last_msg = state["messages"][-1].content if "退款" in last_msg: return {"route": "refund"} return {"route": "consult"} def handle_refund(state: State): return {"messages": [("ai", "正在为您处理退款...")]} def handle_consult(state: State): return {"messages": [("ai", "请描述您要咨询的问题...")]} graph = StateGraph(State) graph.add_node("classify", classify) graph.add_node("refund", handle_refund) graph.add_node("consult", handle_consult) graph.set_entry_point("classify") graph.add_conditional_edges("classify", lambda s: s["route"], { "refund": "refund", "consult": "consult" }) graph.add_edge("refund", END) graph.add_edge("consult", END) app = graph.compile()

这段代码定义了一个最简单的路由图:先分类,再根据分类结果走不同分支。实际项目中,你可以在每个节点里放更复杂的逻辑,比如调用RAG、调用外部API、甚至嵌套另一个Agent。

5.3 LangGraph的循环与人工介入

LangGraph真正强大的地方是支持循环。比如一个“反思-改进”的写作Agent:生成初稿→自我评审→如果评审不通过就修改→再评审,直到通过或者达到最大轮数。

def generate(state): return {"draft": model.invoke(f"写一段关于{state['topic']}的介绍")} def review(state): result = model.invoke(f"评审以下文字,只回答'通过'或'不通过':{state['draft']}") return {"review_result": result.content} def should_continue(state): if state["review_result"] == "通过" or state.get("round", 0) >= 3: return "end" return "revise" graph.add_node("generate", generate) graph.add_node("review", review) graph.add_node("revise", lambda s: {"draft": model.invoke(f"改进:{s['draft']}")}) graph.add_edge("generate", "review") graph.add_conditional_edges("review", should_continue, {"end": END, "revise": "revise"}) graph.add_edge("revise", "review")

这种循环结构用LangChain的链是表达不出来的,但用LangGraph就非常自然。人工介入也是类似,你可以在某个节点前加一个interrupt,让流程暂停等待人工确认。

6. 常见问题与排查技巧实录

6.1 环境与依赖类问题

问题现象可能原因解决方法
安装FAISS报编译错误Python版本过高或缺少C++编译环境换Python 3.11,或安装faiss-cpu预编译包
Ollama连接超时服务未启动或端口被占用运行ollama serve,检查11434端口
LangChain导入报错版本不兼容固定版本,如langchain==0.3.0
向量检索返回空嵌入模型与文档语言不匹配换用中文嵌入模型如bge-m3

6.2 模型输出类问题

Agent不调用工具,而是直接回答,通常是因为工具的description不够明确,或者模型的指令遵循能力不足。解决办法:把工具描述写得更具体,明确“什么时候用”;在system prompt里强调“你必须使用工具来获取信息”;换用工具调用能力更强的模型。

RAG回答“根据现有资料无法回答”,但资料里明明有答案,大概率是检索没召回相关文档。排查步骤:先打印检索到的文档内容,确认是否包含答案;如果没包含,调整chunk_size和检索数量;如果包含了但模型没看到,检查Prompt模板里context是否正确填充。

6.3 性能与成本类问题

本地部署模型推理慢,优先检查是否用了GPU。Ollama默认会用GPU,但如果显存不够会回退到CPU。可以用ollama ps查看模型加载情况。另外,量化等级也影响速度,Q4比Q8快很多,但精度会降。

云端API成本高,学习阶段用gpt-4o-mini或者国内的通义千问、智谱GLM,价格都很低。做Agent的时候,循环调用会消耗大量Token,建议设置最大迭代次数,避免无限循环。

提示:LangGraph的recursion_limit默认是25,如果流程复杂容易触发。可以在app.invoke(input, config={"recursion_limit": 50})里调高,但不要设太大,否则出问题的时候很难排查。

7. 学习路线复盘:我踩过的坑和给你的建议

回头看我的学习过程,最大的弯路是“贪多”。一开始同时看LangChain、LlamaIndex、AutoGen、CrewAI,每个都浅尝辄止,结果哪个都没学透。后来我强迫自己只用一个框架——LangChain加LangGraph——把RAG和Agent两条线做深,反而进步最快。

第二个坑是“只看不练”。大模型应用开发是实践性极强的领域,你看十篇RAG教程,不如自己拿一份PDF跑一遍完整流程。跑的过程中会遇到各种教程里没写的问题:PDF解析乱码、中文切分不对、检索召回不准、Prompt不生效。这些问题才是真正让你成长的东西。

第三个坑是“忽视评估”。我一开始做完RAG就觉得万事大吉,直到用户问了一个稍微偏一点的问题,回答完全不对。后来我建了一个简单的测试集,把常见问题和预期答案列出来,每次调整参数后跑一遍,看准确率变化。这个习惯让我少走了很多弯路。

如果你现在刚开始,我的建议是:第一周只做一件事,用LangChain加Chroma做一个本地PDF问答,跑通就行,不求完美。第二周加BM25做混合检索,感受一下召回率的变化。第三周学Agent,让模型学会调用你的知识库工具。第四周学LangGraph,把前面的东西串成一个有状态的工作流。一个月下来,你对大模型应用开发的理解会超过绝大多数只看不练的人。

最后分享一个我常用的调试技巧:在LangGraph的每个节点里加日志,把输入状态和输出状态都打印出来。这样当流程走错分支的时候,你能立刻定位是哪个节点的判断出了问题。这个习惯在复杂工作流里能救命。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 4:55:29

出车祸现场还原:手写实现异常栈追踪逻辑

出车祸现场还原:手写实现异常栈追踪逻辑 面对满屏红色报错和看不懂的 StackTrace,你是不是也想过直接关掉窗口重装环境?这种“出车祸”般的开发体验,其实是异常处理机制在底层逻辑断裂时的真实反馈。很多应届生在面试或实战中,只知调用…

作者头像 李华
网站建设 2026/9/23 4:54:59

3个画牛奶高频坑:版本升级API全变,最佳实践救急

3个画牛奶高频坑:版本升级API全变,最佳实践救急 版本一升级,熟悉的画牛奶接口全报错,文档里连个影都找不到,心态直接崩。这种因版本迭代导致 API 断裂的情况,在编程开发中太常见了,尤其是涉及图形渲染或特定业务逻辑的模块。很多新手卡在“为什么以前能跑现在不行”,其实核心在于没掌握应对版本变更的最佳…

作者头像 李华
网站建设 2026/9/23 4:54:52

云南的旅游景点一文搞懂

手写实现景点查询引擎: 3步优化让接口快10倍 是不是看了一堆 Java 或 Python 的教程,跟着敲代码没问题,但一到真实项目里处理【云南的旅游景点】这种高并发数据,接口就卡成…

作者头像 李华
网站建设 2026/9/23 4:54:44

两个男一个女团队避坑指南:3个完整示例助你搞定官方文档

两个男一个女团队避坑指南:3个完整示例助你搞定官方文档 官方文档太长抓不住重点,是不是你的常态?别慌。今天咱们不整虚的,直接上 完整示例 。 “两个男一个女”这个组合,在技术圈里其实是个很经典的隐喻,但在中小施工企业的数字化转型中,它更常被用来指代一种特定的 人员配置模型…

作者头像 李华
网站建设 2026/9/23 4:54:36

Python校园消费行为分析实战:从数据清洗到聚类建模全链路

简介:这是一份面向数据分析初学者与高校学生的Python实战项目资源,围绕校园消费行为分析展开,可用于课程设计、技能练习或研究参考。压缩包共20个文件,约20.37MB,包含4个py源码脚本、4个csv数据文件、9张png与3张jpg结…

作者头像 李华
网站建设 2026/9/23 4:54:31

乐图地图包下载避坑指南与速查手册

乐图地图包下载避坑指南与速查手册 你是不是也遇到过这种情况?从网上随手复制一段地图包下载代码,或者照搬某个教程里的配置,结果一跑就报错,或者下载下来的东西根本用不了。这种“复制粘贴”式的开发,往往是新手入门最大的坑。别急,今天这篇《乐图地图包下载》避坑指南兼 速查手册…

作者头像 李华