十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LLM应用工程化实践:从RAG到Agent的技术选型与落地指南

LLM应用工程化实践:从RAG到Agent的技术选型与落地指南 做LLM应用这块也快一年了手头攒了一堆自己写过的、跟人合作过的、以及从社区里扒下来反复改过的项目源码。最近终于抽出时间把它们统一整理成了一个类似 awesome-llm-apps 的资源合集既是给自己做个沉淀也是给团队新同学一份能直接“抄作业”的地图。整理的过程比写代码本身更能逼人思考因为你要把散落的应用案例按场景、技术栈、难度重新归类搞清楚每个项目解决的是什么问题值不值得别人再花时间看。这篇文章就把我这轮梳理时的思路、选型依据、以及对各类LLM应用落地的一些实测感受写出来希望能给正在做技术选型或者打算入坑LLM应用开发的朋友一点参考。在整理这个合集之前我花了不少时间刷各种 LLM 相关的热词和社区动态。说实话现在这个领域信息爆炸到夸张每天都有新框架、新模型、新应用冒出来但真正能经得起推敲、值得放进合集的并不多。我的筛选标准其实很简单要么在技术思路上有启发性要么在工程实现上有可复用的细节要么能真实反映LLM应用在特定场景下的边界。三个都不沾的对不起不管你star数多高我也不会放进来。这个标准可能在很多人看来有点苛刻但既然要做 awesome 列表质量门槛一定得立住。1. 先把LLM应用的全景图铺开到底有哪些类型值得做整理的过程中我先把当前主流LLM应用做了个大致的分类。这一步很关键因为不同类型的LLM应用在技术选型、架构设计、甚至评估方式上差异都非常大。如果你一上来就扎进某个具体项目里很容易只见树木不见森林做出一个demo容易想打磨成能扛住真实流量的产品就抓瞎了。1.1 从“ChatBot”到“Agent”能力层级决定架构复杂度我习惯把LLM应用按“自主性”从低到高排成一条线最底层是传统的聊天机器人往上依次是增强检索的问答系统RAG、需要调用外部工具的任务型应用最顶端就是现在特别热的 Agent 类应用也就是自主智能体。聊天机器人这块看起来简单无非就是包装一下模型接口但真要做得可用需要考虑多轮对话管理、上下文裁剪、语气一致性这些问题。RAG 类的应用是目前落地最广的企业知识库问答是典型场景它的核心挑战不在模型而在数据侧文档怎么切分、Embedding 模型怎么选、召回结果怎么重排。工具调用和 Agent 类的应用是现在最能体现 LLM 价值的方向但也最复杂因为你要面对的是模型不可控的推理过程和外部环境的不确定性。整理合集时我会把项目明确标注属于哪个层级这样使用列表的人可以按自己的实际需求去选择参考对象。想做知识库问答的直接看 RAG 类项目就行不用被 Agent 项目的复杂性吓到。1.2 按应用场景分类通用工具、垂直领域与基础设施除了按能力层级分场景维度也很重要。我把合集中的项目归成了三大类。第一类是通用生产力工具比如智能写作助手、会议纪要生成、代码辅助工具。这类项目通用性最强受众广技术栈也比较成熟非常适合作为学习 LLM 应用的入门参考。第二类是垂直领域应用比如法律文书审查、医疗报告解读、金融研报分析。这类项目往往需要领域知识注入要么靠 RAG 把外部知识库接进来要么靠微调让模型熟悉特定领域的表达习惯。它们的共性是壁垒不在模型能力而在对业务的理解和数据工程质量上。第三类是基础设施和开发框架比如各类 LLM 应用开发框架、Agent 编排工具、可观测性平台。这类项目面向的是开发者本身关注的是怎么把应用开发效率提上去。无论是 LangChain 这类大而全的框架还是某种轻量级的 Agent 脚手架都在这个范畴里。这三类对应的是不同的学习路径和投入策略。如果你是一个独立开发者想快速验证一个想法第一类的参考价值最高如果你所在的企业想解决特定业务问题第二类项目的思路可能更有启发如果你想做开源项目积累影响力第三类是比较容易出成果的方向。2. 框架选型LangChain、LlamaIndex、Haystack 还是自己写胶水代码框架选型是每个做 LLM 应用的人绕不开的决策点。我在整理合集的过程中翻了很多项目的技术栈发现一个有意思的现象早期项目大家几乎都在用 LangChain但后来有相当一部分项目转向了更轻量的方案。这个变化背后是有原因的。2.1 大而全的 LangChain 与“抽象泄漏”的现实困境LangChain 确实功不可没它是最早把 Chain、Agent、Memory 这些概念普及开的框架社区生态庞大能找到几乎所有你想用的模型和工具集成。但它的问题在于抽象层级太多出了问题排查链路会变得特别长。我们在实际项目中经常遇到的情况是一个很简单的 prompt 拼接框架内部却帮你做了很多“智能”的额外处理一旦输出结果不符合预期你很难确定是模型的问题、prompt 的问题还是框架内部某个环节出了问题。这就是典型“抽象泄漏”问题的体现。框架承诺帮你屏蔽复杂性但当复杂性和不确定性来自模型本身时封装得再好也无济于事。所以我现在的态度是也可以用但团队必须有人能读懂框架源码否则出了问题只能干瞪眼。2.2 LlamaIndex 与 Haystack围绕数据还是围绕流水线LlamaIndex 走的是另一个路线它更强调文档的索引和检索你可以把它看作“数据框架”RAG 场景是它的绝对主场。如果你主要做知识库类应用LlamaIndex 提供的 Document、Node、Index 这一套概念非常贴合实际需求数据接入和检索链路都封装得很完善。Haystack 则是另一个值得关注的选手它更强调 NLP 流水线的概念在没有 LLM 爆火之前就是做问答系统的老牌框架。它的一大优势是生产环境友好性组件化设计得很干净而且支持比较完善的评估和监控机制适合对工程质量要求比较高的团队。我在合集中会选择性地收录这三类框架的典型项目。如果你问我怎么选我的建议是团队小、想快速验证想法直接自己写 glue code别急着上框架处理复杂文档场景LlamaIndex 可以当主力要搭一个端到端的生产级 NLP 系统Haystack 值得研究。2.3 自己写胶水代码把控制权攥在手里最后说说我自己现在最常用的方式——自己写胶水代码。不是说完全不用框架而是核心链路自己控制框架只负责解决单一问题。比如我可以用 LlamaIndex 做数据解析和索引但 Retrieval 之后的重排、Prompt 的组装、多轮对话的状态管理这些全都会自己写。好处很明显每一环都在掌控之中出了问题能很快定位模型升级了接口适配成本也低。坏处是开发速度确实慢一些很多边角功能得自己造轮子。但现在 LLM 应用的主流模式其实已经比较清晰了一顿 Prompt 编程加 API 调用真的没必要为了一两个工具函数引入一个几百 MB 依赖的框架。3. RAG 应用的完整实操从文档解析到召回排序的关键细节RAG检索增强生成是当前 LLM 应用里落地最扎实的方向套路已经很成熟了但把细节做好并不容易。我针对合集中几个经典 RAG 项目做了一个梳理把我们自己在实战中积累的经验也补充进去这里重点说说那些容易踩坑的地方。3.1 数据准备不重视后续全部白费很多团队在 RAG 项目上踩的第一个大坑就是对文档解析和清洗投入严重不足。大家觉得 PDF、Word 转成纯文本还不容易吗真做起来就知道PDF 转出来经常是乱的文本顺序错乱、表格结构丢失、页眉页脚混入正文这些问题不对症下药后续再牛的检索模型也救不回来。我的经验是在管线初期的数据清洗阶段至少投入整个项目 30% 以上的精力。PDF 解析建议用支持布局分析的工具不只是提文本还要尝试还原阅读顺序。表格数据尽量转成 Markdown 格式这样对 LLM 更友好。另外要建立一套清洗规则库比如统一编码、去除水印、规范化空白字符对扫描件还需要 OCR 环节。这些工作很繁琐但直接影响最终效果的上限。3.2 文本切分的策略选择固定长度只是一个起点文本切分是 RAG 里绕不开的环节学术界和工业界都做了大量尝试。单纯的按固定字符切分在简单场景下能用但面对层级结构明显、章节语义完整的文档时固定长度切分往往会把完整语义砍断导致每个切片都是残缺片段检索召回的效果大打折扣。现在比较推崇的是“结构化切分”也就是先按文档结构切比如 Markdown 标题层级、HTML 标签、PDF 的 Heading 信息再在结构块内部考虑是否继续细分。对于长文本还会用到递归切分或者语义切分——先做 Embedding再根据向量的相似度突变点来确定边界。这些方法各有适用场景没有银弹。切分策略要考虑检索的粒度匹配问题。用户的 query 往往是一个具体问题对应的答案可能只存在于某个小段落里如果切分粒度过大检索出来的片段会掺杂大量不相关信息干扰模型生成。我个人习惯是切分块大小在 300 到 800 个 token 之间同时做好 overlap保留切分位置的上下文缓冲。对特殊类型的文档再针对性调整参数。3.3 Embedding 模型选型与混合检索的落地经验Embedding 模型的选择直接影响召回的准确率。现在中文场景下比较好的选择有很多比如 BGE、M3E 系列英文场景里 OpenAI 的 text-embedding-3 系列和开源领域的 BGE-M3 也都很常用。但要注意追求单一指标最高的模型不一定是最适合你的要考虑推理速度、向量维度、硬件要求这几个因素。一个需要避开的误区是直接使用某个通用 Embedding 模型对付所有场景。如果你的文档是法律、医疗这类高度垂直的内容用通用模型做出来的向量往往在语义相似度上表现不佳。这种情况下可以考虑用领域数据对 Embedding 模型做继续训练即便只是几十万条领域句对也能带来明显的效果提升。此外在实战中还发现单纯依赖向量检索往往不够。倒排索引BM25基于字面匹配向量检索基于语义匹配两者侧重点不同在很多场景下把两者做加权融合可以显著提升召回率。这种混合检索方案在长尾专有名词、ID 编号等场景里尤其管用。3.4 召回到生成之间的重排环节不能省很多入门级的 RAG 项目检索到 top-k 就直接拼 prompt 丢给 LLM 了中间完全没有重排环节。这种做法在文档数量少、碎片化不严重的时候问题不大但一旦知识库规模上来、召回结果中主题相近的片段很多模型就容易被不相关的那些内容带跑偏。重排Rerank的作用就是打一个更精准的相关性分数把最可能包含答案的内容挑到最前面。现在常用的 rerank 模型有 bge-reranker 系列也有通过 LLM 做 Listwise 排序的做法。实际使用中重排对最终答案准确率的影响非常显著而且推理成本相对可控。这是投入产出比极高的一环。一个完整的 RAG 链路大概率要长这个样子Query 预处理、混合检索、合并打分、重排截断最后才是 Prompt 组装。4. Agent 应用让模型学会“调用工具”背后的工程化难点Agent 是这两年被讨论最多的方向。大家都期待 LLM 不只是回答和总结而是能自己规划任务、调用工具、执行动作、完成一个复杂的业务目标。想法确实美好但工程化落地的坑非常多。4.1 规划能力没那么神奇本质是 Prompt 工程加循环控制很多 Agent 框架的实现核心并不神秘本质上就是你给模型设定一个任务同时把可用的工具列表和调用约束告诉它然后模型输出一个行动计划你的代码负责执行这个计划再把结果返回给模型让它决定下一步做什么。这就是 ReAct 模式的大致逻辑。这里最难搞的其实是循环控制。模型在哪个条件下应该停止调用工具连续出错怎么办工具返回结果超时怎么办这些都是工程上必须考虑的问题。我的经验是要给 Agent 设置严格的最大迭代上限同时要监控每次工具调用的成功率和耗时。如果发现 Agent 陷入重复调用同一工具的循环需要一个外部机制把它强制拉出来。比如检查到连续三轮工具调用结果没有变化时就主动终止流程返回当前结论并提示用户。4.2 工具描述的规范性直接影响模型能否正确调用如果工具给不好Agent 就会一直瞎猜所以工具描述这件事绝对值得花时间打磨。我们最初的 Agent 效果非常不稳定后来发现一个关键问题是我们工具描述写得太随意了。有一段描述是“获取用户地址”直觉上没问题但模型有时会忽略地址类型这个参数收货地址和发票地址是两张不同的表导致大量需要区分场景的请求执行出错。后来我们参考 Function Calling 的最佳实践重新规范了工具描述明确描述工具的参数列表、参数类型、必填项与选填项提供一个或者两个参数取值示例更要说明这个工具在什么场景下适用、什么场景下不该用。改完之后工具调用的准确率提升明显。这件事告诉我们一个道理大模型的使用质量很大程度上取决于你描述事物的质量。4.3 记忆与状态管理Agent 应用最容易翻车的地方传统应用开发中状态管理是一等公民但到了 LLM 应用里很多人却忽略了它。对于需要多轮交互的 Agent状态和记忆是决定用户体验的核心也是最容易出 bug 的地方。短期记忆通常靠把最近的对话历史塞进上下文但要控制 token 长度否则既费钱又影响模型对重点信息的注意力。中期记忆可以是系统运行时保存的关键状态变量比如用户的选择、流程进度。长期记忆就需要持久化存储可以是向量数据库在需要时把和当前对话相关的历史内容检索出来让 Agent 调用。如果你要做一个可落地的 Agent 应用我强烈建议你用带持久化的状态存储方案比如把对话状态存到 Redis 或者关系型数据库里而不是靠一个 Python 变量在那里扛着。进程一重启记忆就全部丢失这本质上就是个玩具。5. 垂域 LLM不是所有场景都该直接 Fine-tuning做 LLM 应用久了一定会遇到来自业务方的“灵魂拷问”能不能用我们的数据训练一个属于我们自己的大模型这个问题本身没毛病但很多人对微调和 RAG 的边界认知是模糊的。5.1 先问 RAG 能不能解决问题再谈微调我的原则是能不微调就不微调。大部分企业内部的知识库问答需求本质上需要的是准确检索和忠实回答RAG直接在推理时调用最新知识更新成本低天然可以追溯到答案来源。什么时候必须微调呢一般来说有这么几类需要模型模仿特定写作风格比如某些品牌的营销文案风格业务涉及大量专业术语和特殊表达方式比如法律条文中的固定句式还有就是要稳定提升在某类任务上的格式遵循能力。注意微调不能无中生有地给模型注入“它本来不知道的知识”想让模型学到具体的业务事实还得靠 RAG。5.2 LoRA 微调的实操流程和数据准备要点如果你确实走到了微调这一步我的建议是用 LoRA。全参数微调依赖的硬件资源比较大一般团队承受不了而 LoRA 冻结原始权重只训练低秩适配矩阵单卡甚至消费级显卡都能跑起来。数据准备是微调里最耗时间也最决定上限的环节。需要提示词、输入、标准输出三要素质量远大于数量。要做清洗和去重要按业务场景划分数据集最好还留出一部分验证集用来对比微调前后模型的表现。训练时可以关注一下 Loss 变化是否平稳但比 Loss 更重要的是在真实业务样例上的效果评估。微调还有一个隐性问题——灾难性遗忘模型可能在适配目标任务的同时把原有的通用能力退化。不同基座模型的表现差异很大在正式启用前一定要用一份覆盖通用能力的测试集比如数学计算、逻辑推理、常识问答来评估模型在微调前后的能力变化。如果出现明显退化就要调整数据配比或者训练超参。5.3 数据工程垂域模型真正的护城河经常有人在社区里问为什么用了某个开源模型做微调效果还是不如商业模型这里面一个很关键的因素是基座模型本身的底子有差距另一个则是你的数据工程能力能否达到应有的水平。垂域数据准备的核心流程是先确定任务边界再针对性采集数据然后是清洗、脱敏、去重、格式化最后做质量抽样评估把不合格的数据踢出去同时分析无效数据暴露的问题反哺数据采集环节。这个过程非常琐碎但它是你积累真正竞争壁垒的地方。好多团队在模型上花的功夫其实不多大量的精力都应该砸在数据管道上。6. 部署与性能优化让 LLM 应用从 Demo 走向生产环境整理合集的时候我发现很多项目在 GitHub 上很热闹但 README 只写了怎么跑 demo完全没有提生产环境需要面对的推理优化、高并发、成本控制等工程问题。这里聊聊我在部署环节积累的几点经验。6.1 推理加速量化、批处理与缓存三板斧LLM 服务的推理速度直接决定用户体验和单位成本。现在开源社区里用的比较多的加速手段无非三个方向量化、连续批处理、缓存。量化是比较常规的优化方式把模型权重从 FP16 降到 INT8 甚至 INT4可以显著降低显存占用。部署时我们通常在 GPU 上跑 FP16 或 INT8CPU 上跑 INT8 或更低的量化版本。量化会带来一定的精度损失但经过评估在可接受范围内时它是性价比相当高的优化。连续批处理是生产环境必须考虑的传统静态批处理会把一个 batch 里最慢的请求拖住其他人而连续批处理允许先完成的请求先返回大幅提升吞吐和响应一致性。这块比较成熟的方案是 vLLM、TensorRT-LLM 这些推理框架。缓存则是容易被忽视但效果立竿见影的手段。LLM 应用里有两层缓存语义缓存对用户输入做 Embedding在向量库里找语义相似的历史问题直接复用之前的答案KV Cache在推理引擎层面对重复前缀做缓存减少重复计算。两层都值得做尤其是语义缓存对常见问题命中后响应时间可以缩小到原来的零头。6.2 模型服务与业务之间的超时、限流和降级机制传统后端开发里你一定会给下游服务设置超时和限流但到了 LLM 服务上这些机制常常被忽略。大模型的推理时间不像普通 API 那样稳定长上下文和复杂生成任务可能会耗掉几十秒一旦业务侧没有设置合理的超时前端体验就会变得非常糟糕。我的建议是把模型调用和业务逻辑解耦不是直接把 HTTP 请求同步挂在模型推理上而是接一个异步任务队列或者消息队列。前端秒回“任务已收到”后台异步执行推理完成后再通过 WebSocket 或者轮询通知结果。这个设计在只有少数用户时体现不出价值但一旦并发上来收益非常明显。降级策略也是必须考虑的。你的模型服务可能会因为请求超时、GPU 故障或限流而不可用这时系统要能优雅降级比如返回一个预先配置的兜底回答或者切换到一个更小的模型先顶上。没有降级策略模型服务一抖动整个产品就和宕机没区别。6.3 可观测性Prompt、Token 与效果的三维监控LLM 应用的可观测性比传统应用多了一层复杂性。传统应用我们主要看日志、指标、链路追踪但 LLM 应用这些都不够还要能追踪每一个 Prompt 具体长什么样、模型返回了什么内容、消耗了多少 Token。我们可以在业务日志里把每次请求的 Prompt注意要对敏感信息脱敏、模型响应全文、token 消耗、耗时全量记录下来。当用户反馈回答质量差时没有这些完整日志基本没法排查。更进一步可以给线上请求做自动评测打标、收集用户显式反馈持续分析线上真实效果。这些都是把一个 LLM 应用从“能跑”推向“可信赖”的必要路径。7. 常见问题与排查技巧实录整理合集加上平时答疑的过程中我积累了一批 LLM 应用开发中的高频问题和排查经验这里整理成一个速查表对新手应该能省不少事。问题现象排查思路解决方案模型回答频繁跑题、缺乏重点大多出在 prompt 约束不足或上下文里噪点太多重新编写 prompt明确任务边界与输出格式裁剪无关上下文考虑引入重排或摘要RAG 召回结果相关性差文本切分不合理、Embedding 模型不匹配、没做混合检索按文档结构切分换领域更匹配的 Embedding在向量检索之外叠加 keyword 检索和重排Agent 不按预期调用工具工具描述不清晰、参数示例缺失、任务目标不明确重写工具描述提供参数样例拆解复杂任务为更简单的子任务必要时加入 few-shot 示例多轮对话记忆混乱历史对话管理策略无效状态没有持久化引入显式记忆槽位并设计状态清理策略用 Redis 或数据库持久化会话状态模型输出格式总是非法 JSON只靠 prompt 约束格式不够温度参数不合适设置温度接近 0用 json mode 或者结构化生成约束层后处理阶段做容错修复与重试服务响应太慢、客户体验差模型过大、请求排队、没有缓存量化或换小模型用 vLLM 连续批处理给重复性问题加语义缓存微调后通用能力退化数据配比失衡或学习率过高降低 LoRA 的 rank 和学习率调整领域数据与通用数据的比例训练后跑通用能力回归测试排查问题的顺序也很重要建议从外向内层层深入先看输入数据有没有问题再检查 Prompt 构造是否正确再看模型调用参数是否合理最后才回到模型本身效果上下结论。不少人一遇到问题就怀疑是模型能力不够实际上大部分情况下是前几环有疏漏。8. 整理 awesome-llm-apps 这轮下来的一些体会经过这番整理如果只能总结一句话那就是LLM 应用开发没有银弹。无论是 RAG、Agent 还是微调技术路线都算不上玄学真正决定一个应用能不能产生价值的是工程化和数据工程的基本功。在合集的最后我也想给准备入坑这个领域的朋友们几段掏心窝的话。第一段关于选型不要被框架绑架也不要迷信某个组件的名气回到你自己的业务场景里把数据、成本、体验、可维护性这四个维度盘清楚再决定技术选型。第二段关于节奏先搭一个最简单的 end-to-end demo验证核心价值成立之后再逐步加复杂度千万不要一上来就规划一个庞大的 Agent 系统或者准备训练一个垂域大模型。第三段关于学习复盘永远比追新更重要把一个经典项目彻底吃透比把一百个项目都收藏起来作用大得多。我计划把这个合集持续维护下去后续会补充多模态应用、推理成本优化还有更细的 Agent 落地案例。如果你也在做 LLM 应用欢迎多交流一起把这个生态的底子打得更扎实一些。
返回列表