1. 从“会用”到“会做”我为什么决定啃下大模型应用开发2023 年那会儿我跟大多数人一样第一次用上 ChatGPT 类的对话产品觉得这东西挺神奇但也就停留在“问一句答一句”的层面。真正让我下决心系统学习大模型应用开发的是一个很现实的问题公司内部有一堆产品文档、接口说明、历史工单新同事上手要翻好几天老同事也经常记不清某个参数到底在哪个版本改过。我当时想能不能做一个能“读懂我们内部资料”的问答助手而不是每次都要把文档复制粘贴到对话框里。这个念头一出来问题就跟着来了。市面上的通用大模型确实聪明但它不知道我们内部的业务逻辑也不知道我们那套祖传接口的命名习惯。你问它“订单状态 302 是什么意思”它只能给你编一个看起来很像的答案。这就是大模型应用开发要解决的核心矛盾通用模型的能力很强但缺乏特定领域的知识和可控的行为边界。而我要学的就是怎么在通用模型之上搭出一层能接入私有数据、能调用外部工具、能按预期流程工作的应用层。所以这篇内容不是那种“大模型学习路线图”式的清单罗列而是我自己从零摸索过来的一条真实路径。我会讲清楚大模型、Agent、LLM、RAG、LangChain 这几个词到底在说什么它们之间是什么关系以及我是怎么一步步把“调 API”变成“做应用”的。如果你也是刚入门的开发者或者已经会写代码但不知道从哪切入大模型方向那这篇内容应该能帮你少走一些弯路。我踩过的坑、试过的方案、最后留下来的那套组合都会尽量讲透。2. 先把概念理清楚LLM、Agent、RAG、LangChain 到底谁是谁2.1 LLM 是发动机不是整车很多人一开始会把“大模型”和“大模型应用”混为一谈。我刚开始也这样觉得学会了调某个模型的接口就算会大模型开发了。后来才明白LLMLarge Language Model大语言模型本质上是一个文本到文本的概率模型。你给它一段输入它根据训练时学到的统计规律预测接下来最可能出现的词序列。它没有记忆没有数据库没有执行能力甚至不知道自己说的是对是错。打个比方LLM 就像一台性能很强的发动机。发动机本身能输出动力但你没法开着发动机上路你得有底盘、变速箱、方向盘、油箱才能组成一辆车。大模型应用开发做的就是造这辆车。DeepSeek、通义、文心这些都属于 LLM 的范畴它们是底层能力提供方。你调用它们的 API拿到的是文本生成结果但要让这个结果真正解决业务问题中间还差好几层。这里有个常见的认知误区有人觉得“模型参数越大越好”于是拼命找最大的模型来用。实际做应用时模型选型要看任务类型、响应延迟、成本和可控性。比如一个内部知识库问答用 7B 到 14B 级别的模型配合好的检索策略效果往往比直接上超大模型硬答要好因为答案的准确性主要来自检索到的资料而不是模型本身的“记忆力”。2.2 RAG 是给模型外挂一个知识库RAGRetrieval-Augmented Generation检索增强生成是我学的第一个真正有用的应用模式。它的思路很朴素既然模型不知道你的私有数据那就在回答问题之前先去你的资料库里把相关内容找出来连同问题一起塞给模型让它基于这些内容来回答。流程拆开看是三步。第一步是索引把你的一堆文档切分成小块每块转成一个向量一串数字存进向量数据库。第二步是检索用户提问时把问题也转成向量去数据库里找最相似的几个文档块。第三步是生成把找到的文档块和原始问题拼成一个提示词交给 LLM 生成最终答案。我一开始觉得这不难不就是“搜索 拼接”吗。真做起来才发现坑全在细节里。文档怎么切切太大检索出来的内容太杂模型抓不住重点切太小上下文断裂答案不完整。向量模型选哪个中文场景下不同模型的检索效果差异很明显。检索回来五条怎么排序、怎么去重、怎么控制总长度不超模型上下文窗口每一步都有讲究。这些后面我会专门展开讲。2.3 Agent 是让模型学会“动手”如果说 RAG 是给模型配了一个资料库那 Agent 就是给模型配了一双手。普通的 LLM 调用是“你问我答”而 Agent 模式下模型可以决定调用哪个工具、按什么顺序调用、根据调用结果决定下一步做什么。举个我实际做过的例子。用户问“帮我查一下上个月销售额最高的三个产品并生成一份简要分析”。纯 LLM 做不到因为它没有数据库访问权限。但在 Agent 架构下模型可以先调用一个“查询销售数据”的工具拿到结果后再调用一个“生成图表”的工具最后把分析文字组织出来。整个过程模型自己规划步骤我只需要把工具定义好。Agent 和 LLM 的关系可以理解成“司机和发动机”。LLM 提供推理和语言能力Agent 框架负责循环执行思考、行动、观察结果、再思考。LangChain 里的 Agent、LangGraph 里的状态图都是在解决这个循环怎么组织、状态怎么管理、异常怎么处理的问题。我个人的体会是Agent 看起来酷但可控性是最大的挑战。模型可能陷入循环、可能选错工具、可能把简单任务复杂化。所以生产环境里我更多用“固定流程 局部 Agent”的混合模式而不是完全放开让模型自由发挥。2.4 LangChain 是胶水不是银弹LangChain 刚出来的时候很多人把它当成大模型开发的“万能框架”。我一开始也这么以为照着教程搭了一个链跑通了觉得挺爽。但用久了会发现LangChain 的价值在于它把常见的模式抽象成了可复用的组件提示词模板、输出解析器、检索器、工具调用、记忆管理。你不用每次都从零写这些逻辑。但它也有代价。抽象层多了出问题时排查链路变长版本迭代快网上教程经常对不上有些场景下直接调 API 加几十行代码反而更清晰。我现在的做法是原型阶段用 LangChain 快速验证生产阶段按需拆解只保留真正带来价值的抽象。LangGraph 则是在 LangChain 基础上针对有状态、多步骤、需要循环和分支的 Agent 场景做的补充它用图的方式描述流程比链式结构更适合复杂控制流。把这四个概念串起来看LLM 是底层能力RAG 是知识增强模式Agent 是行动增强模式LangChain/LangGraph 是组织这些模式的工程框架。学习顺序上我的建议是先搞懂 LLM 调用和提示词再上手 RAG最后碰 Agent。跳过前两步直接做 Agent很容易做成一个“看起来很智能但实际不可用”的玩具。3. 我的学习路径从调通第一个接口到跑起完整应用3.1 第一阶段把 API 调用和提示词玩熟我最开始的两周什么都没搭就是反复调接口。找一个支持中文、有免费额度的模型平台注册、拿密钥、写一个最简单的 Python 脚本把问题发过去把回答打印出来。这一步的目的不是做出什么东西而是建立对模型行为的直觉。我会刻意做几类测试。同一问题换不同问法看回答稳定性给一个需要分步骤推理的问题看它会不会跳步给一个它肯定不知道的内部信息看它是承认不知道还是硬编。这些测试让我明白了一件事模型的输出质量很大程度上取决于你给它的输入质量。提示词不是随便写一句话而是要明确角色、任务、约束和输出格式。这个阶段我踩的第一个坑是密钥管理。一开始图省事把 API Key 直接写在代码里后来要传到代码仓库才意识到这有多危险。正确的做法是用环境变量或者配置文件管理密钥代码里只读不写。如果是团队协作还要确保配置文件不被提交到版本控制。这个习惯越早养成越好后面做 Agent 调用多个服务时密钥会更多管理混乱的代价更大。提示词方面我总结了一个自己常用的结构先给模型一个身份“你是一个严谨的技术文档助手”再给任务“根据以下资料回答问题”再给约束“只使用资料中的信息资料中没有的就说不知道”最后给格式“用三段话回答每段不超过 100 字”。这个结构不复杂但能显著减少模型胡编和跑题的情况。3.2 第二阶段动手搭一个最小可用的 RAG提示词玩熟之后我开始做 RAG。第一个版本极其简陋把几个 Markdown 文件按段落切开用一个开源的中文向量模型转成向量存进本地向量库检索时取相似度最高的三条拼进提示词。就这么个东西跑起来的效果已经让我有点惊讶了——它真的能回答出文档里的具体内容而不是泛泛而谈。但很快问题就暴露了。有一次我问“配置项 timeout 的默认值是多少”检索出来的三条里两条是无关的部署说明一条是正确内容但被切成了两半关键数字在另一块里。模型拿到这种残缺上下文给出的答案自然不对。这让我意识到RAG 的效果瓶颈往往不在生成端而在检索端。于是我开始调分块策略。最初按固定字数切后来改成按语义切优先在标题、段落、列表项这些自然边界处断开同时控制每块在 300 到 500 字之间块与块之间留一点重叠避免上下文断裂。重叠大概取块大小的 10% 到 15%这个比例是我试出来的太小了接不上太大了检索结果冗余。向量模型我也换过几个。中文场景下有些通用模型对技术术语的区分度不够“超时时间”和“重试次数”这种语义相近但含义不同的词检索时容易混。后来我选了一个在中文语义相似度任务上表现更稳的模型检索准确率明显提升。这里没有绝对的最优解关键是用你自己的数据做小规模评测准备二三十个问题和对应答案看检索出来的内容里有没有正确答案命中率是多少再决定换不换模型。3.3 第三阶段引入 LangChain 重构理解框架的边界手写 RAG 跑通后我开始用 LangChain 重构。动机很简单我想加对话记忆、想支持多种文档格式、想接入工具调用如果全手写代码会越来越乱。LangChain 把这些都封装好了用起来确实快。但重构过程中我也踩了坑。LangChain 的文档更新很快网上搜到的教程经常和当前版本对不上某个类名改了、某个参数位置变了照着抄就报错。我的应对方法是以官方文档为准教程只用来理解思路。遇到报错先看堆栈定位到具体是哪个组件的问题再去查对应版本的文档。另一个体会是LangChain 的链式结构适合线性流程但一旦涉及条件分支和循环就会变得别扭。比如“如果检索结果为空就换个关键词重新检索最多重试两次”用链写起来很绕。这时候 LangGraph 的图结构就体现出优势了节点是处理步骤边是流转条件状态在节点间传递逻辑一目了然。我现在的项目里简单的问答用 LangChain 链复杂的多步骤流程用 LangGraph 图两者并不冲突。3.4 第四阶段做第一个 Agent 项目真正让我对 Agent 有体感的是一个内部工具调用的小项目。需求是用户用自然语言描述一个查询需求系统自动判断该查哪个数据源、用什么参数、返回结果后做简单汇总。我定义了三四个工具函数每个函数有明确的名称、描述和参数说明然后让模型根据用户输入决定调用哪个。第一次跑通的时候挺兴奋但紧接着就发现模型会“想太多”。一个简单的“查一下昨天的订单数”它有时候会先调用一个无关的工具再调用正确的工具白白多花一次调用。后来我调整了工具描述把每个工具的适用场景写得更具体同时在提示词里明确“只调用必要的工具不要做额外操作”情况才好转。这个阶段最大的收获是Agent 的可靠性取决于工具定义的清晰度和流程约束的严格程度。工具名称要见名知意描述要说清楚“什么时候用”和“什么时候不用”参数要有类型和示例。如果工具有副作用比如写操作一定要加确认机制不能让模型自己决定就执行。我见过有人让 Agent 直接操作数据库结果模型生成了一个删除条件写错的语句这种风险在生产环境里是不能接受的。4. 核心环节拆解RAG 和 Agent 的实操细节4.1 文档处理分块策略决定检索上限RAG 的第一步是把原始文档变成可检索的块。这一步做不好后面怎么调都白搭。我处理过的文档类型包括 Markdown、PDF、Word 和网页每种都有各自的坑。PDF 最麻烦尤其是带表格和双栏排版的。直接按文本提取顺序经常是乱的。我的做法是先用解析库把 PDF 转成结构化文本保留标题层级表格单独抽出来转成 Markdown 表格再进入分块流程。如果 PDF 是扫描件还得先做文字识别这一步的准确率直接影响后续效果。分块我目前用的是“递归字符分割 语义边界优先”的组合。具体来说先按标题切大块如果某块还是太长再按段落切段落还长就按句子切。每个块保留一定的元数据来源文件名、所属章节、块序号。这些元数据在检索时很有用可以按来源过滤也可以在答案里标注引用出处。注意分块大小没有万能值。技术文档适合 300 到 500 字法律合同可能要到 800 字才能保持条款完整聊天记录则适合按对话轮次切。一定要拿自己的数据试看检索命中率再定。4.2 向量检索相似度不是唯一标准向量检索的基本逻辑是算余弦相似度取最高的几条。但实际用下来纯向量检索有几个明显短板。一是对精确匹配不敏感比如查一个具体的错误码“ERR_5023”向量模型可能把它和“ERR_5024”混在一起。二是对否定和条件不敏感“不支持的功能”和“支持的功能”向量距离可能很近。我的改进方案是混合检索向量检索负责语义召回关键词检索负责精确匹配两路结果合并后重新排序。关键词检索可以用简单的倒排索引也可以用支持中文分词的搜索引擎。合并时给两路结果不同的权重具体权重靠评测调。这个方案实现起来不复杂但效果提升很明显尤其是查具体参数、错误码、版本号这类场景。重排序是另一个提升点。初次检索召回比如 20 条用一个专门的重排序模型对这 20 条按与问题的相关度重新打分取前 5 条送给 LLM。重排序模型比向量模型更重但只用在少量候选上成本可控。我实测下来加了重排序之后答案准确率能提升一截尤其是问题比较模糊的时候。4.3 提示词组装把检索结果用好检索回来的内容怎么放进提示词也有讲究。我见过有人直接把检索结果拼接成一长段结果模型分不清哪些是资料、哪些是问题。我的做法是用明确的分隔标记比如把每条资料用编号和来源标出来然后明确告诉模型“以下资料按相关度排序请优先使用靠前的资料”。还有一个细节是控制上下文长度。模型的上下文窗口有限检索结果太多会挤占空间还可能引入噪声。我的策略是先按重排序分数截断保证总长度不超过窗口的 70%留出空间给系统提示和用户问题。如果资料确实很多就只保留最相关的几条并在提示词里说明“资料可能不完整如无法回答请明确说明”。对于需要引用来源的场景我会要求模型在答案里标注用了哪几条资料。这样一方面方便用户核实另一方面也倒逼模型基于资料回答减少胡编。实现上就是在提示词里加一条格式要求然后在输出解析时提取引用编号。4.4 Agent 工具设计让模型知道什么时候该动手Agent 的核心是工具调用而工具调用的成败八成取决于工具定义。我总结了几条实操原则。工具名称要动词开头、含义单一。比如“查询订单”比“订单处理”好“发送邮件”比“消息操作”好。模型看到名称就能大致判断用途减少选错的可能。工具描述要写清楚三件事这个工具做什么、什么时候用、什么时候不用。比如“查询订单状态根据订单号查询当前状态。适用于用户提供了明确订单号的场景。如果用户只给了用户名没有订单号不要调用此工具应先调用用户查询工具。”参数要带类型、说明和示例。模型对参数的理解依赖描述描述越具体传参越准确。对于枚举类型的参数把所有可选值列出来。对于可选参数说明默认行为。提示工具数量不要一次给太多。我试过给模型十几个工具结果它选择困难经常调错。后来按场景分组每次只暴露相关的五六个工具准确率明显上升。4.5 状态管理与异常处理让流程稳下来Agent 跑起来之后最怕的是卡死和跑偏。卡死通常是模型陷入循环反复调用同一个工具跑偏是模型理解错了任务越做越远。我的应对是在流程层面加约束。设置最大步数比如最多执行 8 步超过就强制结束并返回已有结果。设置工具调用白名单某些高风险工具在特定场景下不允许调用。对工具返回结果做校验如果返回为空或格式异常给模型一个明确的错误提示让它决定重试还是放弃。LangGraph 在这方面帮了我不少忙。它用状态图管理整个流程每个节点的输入输出都有明确类型条件边决定下一步走哪里。我可以清楚地看到流程在哪个节点卡住也方便加日志和断点。相比链式结构图结构在调试复杂流程时优势明显。5. 常见问题与排查技巧实录5.1 检索不准先查分块再查模型检索不准是最常见的问题。我的排查顺序是先看分块是否合理再看向量模型是否适合最后看检索策略是否需要调整。分块问题表现为正确答案所在的块被切碎了或者块太大导致关键信息被淹没。解决办法是调整分块大小和重叠比例或者改用语义分块。向量模型问题表现为语义相近但含义不同的内容被混在一起。解决办法是换一个在中文语义任务上表现更好的模型或者引入关键词检索做补充。检索策略问题表现为召回数量不够或排序不合理。解决办法是增加召回数量、引入重排序、调整混合检索权重。我一般会准备一个小的评测集二十到五十个问题每个问题标注正确答案所在的文档块。每次调整策略后跑一遍看命中率变化。没有评测集调优就是盲人摸象。5.2 模型胡编用提示词和检索双重约束模型胡编的原因通常有两个一是检索没找到相关内容模型只能靠自己编二是提示词没有明确约束模型觉得自由发挥也没关系。针对第一个原因可以在检索结果为空或分数过低时直接返回“未找到相关信息”而不是硬让模型回答。针对第二个原因提示词里要明确“只使用提供的资料回答资料中没有的信息不要编造如果不确定就说不确定”。我还会在输出解析时做检查如果答案里出现了资料中没有的关键实体就标记为可疑人工复核。5.3 响应太慢定位瓶颈再优化大模型应用的响应时间由几部分组成检索时间、模型生成时间、网络传输时间。检索通常很快除非向量库很大或重排序模型很重。模型生成时间是大头尤其是输出长文本时。优化方向有几个。一是换更小的模型做简单任务复杂任务才用大模型。二是流式输出让用户先看到部分结果感知上更快。三是缓存相同或相似的问题直接返回缓存结果。四是并行化检索和某些预处理可以并行执行。我实测下来流式输出对用户体验的提升最明显虽然总时间没变但用户不会觉得卡。5.4 密钥泄露从第一天就养成好习惯密钥管理是个老生常谈但总有人栽跟头的问题。我的做法是密钥只存在环境变量或专用的密钥管理服务里代码里通过读取环境变量获取。本地开发用.env文件但.env必须加入.gitignore。团队协作时每个人用自己的密钥不要共享。如果密钥不小心提交到了代码仓库第一时间去平台吊销并重新生成不要心存侥幸。对于 Agent 调用多个外部服务的场景密钥会更多。我建议按服务分类管理命名清晰比如ORDER_API_KEY、MAIL_API_KEY避免混用。定期轮换密钥也是个好习惯尤其是人员变动时。5.5 常见问题速查表问题现象可能原因排查方向解决思路答案与资料不符检索结果无关或提示词约束不足检查检索命中率、检查提示词优化分块、加混合检索、强化提示词约束模型说不知道检索未召回相关内容检查分块和向量模型调整分块策略、换向量模型、增加召回数响应时间过长模型生成慢或流程步骤多分段计时定位瓶颈流式输出、换小模型、缓存、并行化Agent 反复调用同一工具工具描述不清或缺少终止条件检查工具定义和流程约束明确工具适用场景、设置最大步数输出格式不稳定提示词格式要求不明确检查输出解析逻辑明确格式要求、加输出校验和重试密钥报错密钥未配置或已失效检查环境变量和密钥状态重新配置、轮换密钥、检查权限6. 我踩过的坑和留下来的经验6.1 不要一上来就追求“全自动”我最初做 Agent 的时候总想着让模型自己规划一切结果做出来的东西时好时坏根本不敢给人用。后来我改成“半自动”固定主流程只在关键决策点让模型做选择。比如查询数据这个流程步骤是固定的——解析问题、确定数据源、生成查询、执行、汇总。模型只负责“确定数据源”和“生成查询”这两步其他都是代码控制。这样可靠性大幅提升开发难度也降低了。这个经验让我明白Agent 的价值不是取代流程而是在流程中处理不确定性。能用代码写死的逻辑就不要交给模型判断。模型适合做模糊匹配、语义理解、自然语言生成这些事不适合做精确计算和状态管理。6.2 评测集比调参更重要有段时间我沉迷于调各种参数分块大小、重叠比例、召回数量、重排序权重。调来调去感觉效果时好时坏但说不清到底哪个改动起了作用。后来我花了一天时间整理了五十个问题和对应的标准答案每次改动后跑一遍评测看准确率变化。有了这个基准调优才变得有方向。评测集不需要很大但要有代表性。问题要覆盖不同类型的查询事实型、比较型、推理型、否定型。答案要明确最好能标注来源文档块。我现在的习惯是每加一个新功能或改一个策略先跑评测再看效果不靠感觉做决定。6.3 日志和可观测性要提前做RAG 和 Agent 的流程比普通接口复杂出问题时如果没日志排查起来很痛苦。我现在的做法是在每个关键节点打日志检索到了哪些块、分数是多少、提示词最终长什么样、模型返回了什么、工具调用的输入输出是什么。这些日志在开发阶段可能觉得冗余但线上出问题时就是救命稻草。对于敏感信息日志里要做脱敏。用户问题、检索到的文档内容可能包含隐私不能原样记录。我的做法是记录摘要和哈希需要详细排查时再通过其他方式获取。6.4 模型选型要务实我试过用很大的模型做所有事效果确实好但成本和延迟都受不了。后来改成分级策略简单任务用小模型复杂任务用大模型需要精确格式的用支持结构化输出的模型。这个策略需要在代码里做路由根据任务类型选择模型。还有一个体会是不要迷信某个模型。模型迭代很快今天最好的明天可能就被超越。把模型调用封装成统一的接口换模型时只改配置不改业务代码。这样既能跟上技术发展又不会被某个平台绑定。6.5 从项目里学比从教程里学快我学得最快的阶段不是看教程的时候而是做那个内部问答助手的时候。因为有问题要解决有数据要处理有坑要填每一步都是真实的反馈。教程给你的是标准路径但真实项目里全是意外。我的建议是学完基础概念后尽快找一个自己能用得上的小场景动手做。哪怕只是把几篇文档做成问答也比只看不练强得多。做项目的过程中你会自然地去查文档、读源码、试方案这种主动学习的效果远超被动接受。而且做完一个项目你对整个链路的理解会从“知道”变成“会做”这是完全不同的层次。6.6 关于 LangChain 和 LangGraph 的选择最后说一下这两个框架的取舍。LangChain 适合快速搭建线性流程组件丰富上手快。LangGraph 适合复杂控制流状态管理清晰调试方便。我的项目里两者都用简单的 RAG 问答用 LangChain 链多步骤 Agent 用 LangGraph 图。如果你刚开始学我建议先手写一遍 RAG理解每一步在做什么再用 LangChain 重构感受框架带来的便利。直接上框架容易变成“只会调 API不懂原理”遇到问题就卡住。手写一遍之后你看框架的封装会更清楚它在帮你做什么也更容易判断什么时候该用、什么时候不该用。这个领域变化很快新工具新方法层出不穷。但底层的东西——怎么把数据处理好、怎么把提示词写好、怎么把流程控制好——这些是不太会变的。把基础打牢再学新工具就是顺水推舟的事。我现在也还在学每次做新项目都会遇到新问题但有了这套底子至少知道该往哪个方向查、该怎么试。
