ARTICLE DETAIL

资讯详情

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

AI工程从零开始:模型推理、RAG检索与Agent编排的落地实践

AI工程从零开始:模型推理、RAG检索与Agent编排的落地实践 当我把这套笔记命名为ai-engineering-from-scratch的时候其实想得很简单我需要一条能从头走到尾的 AI 工程路线而不是零碎的知识点合集。那时候全网的 ai-engineering 内容基本分两类一类是算法大佬在讲 Attention 是怎么算出来的另一类是卖课的在教怎么调 Prompt 和接 API真正讲“落地工程链路”的东西反而很少。这篇博文就是我本人从传统后端转过来啃 AI 工程的一份实录没有花哨的标题党聊的是模型推理怎么选型、RAG 为什么总在检索环节翻车、Agent 的 function calling 到底该怎么设计还有上线前后怎么评测、怎么监控成本。适合后端工程师、想做 AI 应用落地的开发者以及看了一大堆教程却不知道从哪下手的朋友。1. 先想明白AI 工程到底在“工程”什么1.1 从“模型能用”到“系统能跑”差了一个身位我做传统后端很多年CRUD、微服务、消息队列是日常直觉上觉得 AI 不就是调一个模型库再包一层 API 吗。真上手才发现AI 工程和算法工程有根本区别算法同学关心的是“模型在某些数据上的指标能不能提升”AI 工程师关心的是“这个模型放进业务系统里能不能稳定服务、效果可控、成本可算”。我带过一个小项目最初只是给内部知识库做一个智能问答 Demo。模型很快跑通了对话效果也像那么回事。可一旦我们要把它接到真实业务流上问题全出来了并发高了以后响应超时、上下文塞太满导致回答漂移、用户问法换个说法就检索不到、成本账单让人不敢看。这些问题没有一个可以通过调 Prompt 解决全部要靠工程手段来兜底。所以我对 ai-engineering 的定义是让大语言模型在真实场景里稳定产生业务价值的整套系统工程。它包含模型推理服务、数据准备与检索链路、Agent 编排、效果评测、可观测性和成本治理。它考的不是谁更懂模型原理而是谁能让模型在系统里长时间不翻车。1.2 为什么“从零开始”这条路必须有路线图如果只是按网上搜到的零散教程去学最典型的死法是这样的今天学一下 LangChain明天试一下微调后天又去看部署工具每样都只摸到皮毛过两周全忘。我踩过这种坑所以我在动手前先画了一条按依赖顺序排列的学习/实践路径先让模型在手里能稳定跑起来再给它接业务数据形成 RAG再让它在多工具场景下自主完成复杂任务最后建立评测和观测体系来量化一切。顺序不能乱因为每一层都是下一层的地基。这篇文章接下来就按这条链路展开。每个章节都会交代清楚“为什么这么做”“选型时纠结什么”“实际操作中有什么坑”尽量让你看完就能在自己的项目里复刻一条最小可用的 AI 工程链路而不是背下一堆名词。2. 第一步把模型跑起来而不是调模型2.1 托管 API 还是本地部署没有唯一答案很多人第一步就卡在选型上是调云厂商的托管模型 API还是在自己服务器上部署开源模型我的结论是这不是技术优劣问题而是阶段和场景问题。我在快速验证想法的阶段一律用托管 API理由很简单开发效率高一个openai客户端就够了不用管 GPU、不用处理高并发试用一个场景最多半天出结果。但如果业务进入生产期或者对数据安全、成本敏感本地部署开源模型就很有必要数据不出内网推理成本可控还能针对业务场景微调。我做过一张对比表可以当作选型参考维度托管 API自部署开源模型上手速度分钟级立刻可调需要环境搭建与配置成本结构按 Token 计费用量涨成本涨固定硬件成本用量大时更划算数据安全数据出网需评估合规数据留在内网可审计技术可控性依赖厂商版本迭代可量化、可微调、可替换运维负担无厂商负责GPU、镜像、监控全部自己扛建议很直白客户端 Demo 用托管 API服务端生产环境按规模与合规要求逐步向自部署迁移。有些场景两者混跑也是正常的——“敏感数据走本地通用能力走 API”是我常用的混合架构。2.2 自部署时最容易忽视的三个指标很多第一次自部署模型的人一看到模型能出结果就觉得“部署成功了”实际上距离“可用”还有很大距离。我只看三个指标显存占用决定了你能在什么样的显卡上跑多大的模型。一个 7B 参数模型在 FP16 精度下光权重就要占大约 14GB 显存这还没算 KV Cache 和运行时开销。如果只有一张 8GB 的消费级显卡对应的策略就应该是选 7B/8B 模型并做 4bit 量化比如 AWQ把显存占用压到 6GB 左右同时优化并发和上下文长度来限制 KV Cache。千万不能只盯着模型参数量显存才是硬约束。吞吐量单位时间能处理的 Token 数直接决定你的接口最多能撑多少并发。我通常用tokens/s来测一次压测把并发从 1 加到 16看吞吐和延迟的曲线变化。大批量并发时吞吐会先升后降找到拐点就是这台机器的合理承载上限。首字延迟Time to First TokenTTFT用户点完发送到看见第一个字出来的时间。这个指标特别影响体验如果 TTFT 超过 2 秒哪怕后面的生成速度再快用户也会觉得系统很卡。特别是做流式输出时TTFT 是决定产品质感的关键数字。我在生产环境选推理框架时工具就是 vLLM它对吞吐和显存管理做了大量优化特别是 PagedAttention 机制让 KV Cache 不再一次性预分配大块显存而是在需要时按页分配连带把显存碎片问题也缓解了。相比之下Ollama 更适合本地体验或小规模使用胜在安装简单但如果要扛真实流量还是直接上 vLLM 更稳。运行一个 qwen2.5-7b-instruct 的典型服务命令我一般写成这样python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192 \ --port 8000特别注意--gpu-memory-utilization不要无脑设成 0.95要留一点空间给采样和其他运行时开销。我原来设过 0.98结果一压测就 OOM后来稳定在 0.85~0.9 才算踏实。3. RAG 不是“接个向量库”就结束的项目3.1 为什么多数落地场景的第一站都是 RAGLLM 的知识是训练时固定的你不知道它训练数据截止到哪一天更不可能让它天然知道你公司内部的规章制度、私有产品文档。RAG检索增强生成解决的就是这件事回答问题时先把相关资料检索出来放进上下文再让模型生成答案。它相当于把“闭卷考试”变成“开卷考试”——模型不需要背下所有知识它只需要学会在你的知识库里找答案。我做过好几个项目无一例外都是同样的演进路径一开始想微调一个垂直模型聊着聊着发现微调的数据成本高、周期长而且业务文档天天在更新总不能天天重新微调。RAG 的优势这时就非常明显知识一变重新建索引就行模型本身不用动。只要答案依赖私有数据和实时信息的场景RAG 都是优先方案。3.2 决定检索质量的三个关键选择“把 PDF 解析一下、向量化、丢进向量库、查一下”是网上最多见的 RAG 教程但它只覆盖了最少 20% 的工作量。真正影响 RAG 质量的是下面三个选择切分策略。原始 PDF 不可能直接丢给模型必须切成片段再向量化。固定长度切分最省事但语义会被人为切断——本来完整的一段技术方案被拦腰分成两片检索时哪一片都缺上下文。我在实践中更推荐“以结构为单位切分”按章节、标题、段落边界先做一轮语义分割然后每个大段落内部再决定是否需要二次切分。切分时还要加一个“重叠窗口”的思路让相邻片段的头尾有重合这样能显著降低关键句恰好落在边界上的概率。Embedding 模型选型。向量化质量直接决定“能不能检索到正确答案”。通用 embedding 模型在垂直领域往往表现一般因为专有名词、内部缩写完全不在它的词汇空间里。我现在默认用 BGE-M3 这类开源模型一个重要优势是支持中英文混合检索同时有稠密向量加稀疏向量的混合召回能力如果领域术语特别密集花时间找一套领域相关语料在通用模型基础上做一次继续预训练或微调性价比往往比折腾 Prompt 高得多。召回与重排。向量检索本质上是近似最近邻搜索第一轮召回的结果不一定是最优的。我现在的标准链路是线向量检索召回 top-50再交给一个独立的 rerank 模型精排只取 top-5 给到大模型。重排相当于在向量召回的大网里捞一遍把语义最贴近问题的那几条挑出来这几乎是我试过的所有 RAG 优化里对最终效果提升最直接的一招。3.3 当我没做重排时检索质量到底有多差说个真实翻车案例。知识库里有一篇文档讲“跨地域容灾部署方案”包含网络拓扑、数据同步、故障切换三个章节。用户问的问题是“数据库切换后怎么处理缓存失效”直觉上这个问题跟“故障切换”和“缓存策略”有关但纯向量检索把“缓存”相关的片段排到了第一而它跟“故障切换后的缓存处理”根本不是一回事最后模型基于这段文字给出了一个答非所问的答案。问题出在向量检索只做语义相似度匹配它对高频词和字面重合过于敏感。自从我把重排环节加进来类似问题的命中率肉眼可见地提升了。评测方法也很简单人工标注 50 个问题分别跑“有重排/无重排”两个链路统计检索到正确答案的比例差异通常在 15 到 30 个百分点。4. Agent 工程从能回答问题到能完成任务4.1 Agent 的核心不是智能而是结构RAG 解决的是“基于资料回答问题”但很多业务诉求是“帮我完成一整套操作”比如“查一下上个月的订单数据汇总异常然后写一封告警邮件”。这已经不是一次问答而是多步骤任务。Agent智能体就是干这个的LLM 做决策决定每一步调哪个工具、传什么参数、得到结果后要不要继续执行下一步。如果你以为 Agent 的核心在于模型“突然聪明了”那就搞错了。在实际工程项目里Agent 能不能跑通90% 取决于外围的结构设计工具协议定义、状态流转控制、内存管理、错误恢复策略。模型负责的只是中间一小段决策。我最常用的 Agent 框架是 ReActReasoning Acting就是让模型交替进行“思考 → 调用工具 → 观察结果 → 再思考”的循环。在这个循环里工程侧要做的是把循环的每一步都做得极其明确。4.2 工程化的三个内部组件第一个是工具管理。Agent 要调用外部能力就必须有明确的工具契约。我一般给每个工具定义成这样{ name: query_sales_data, description: 查询指定时间范围内的销售统计数据, parameters: { start_date: {type: string, description: 开始日期格式YYYY-MM-DD}, end_date: {type: string, description: 结束日期格式YYYY-MM-DD} } }模型通过 function calling 的结构化输出选择工具并填充参数。这里最大的坑是工具描述写得太抽象模型就不知道该什么时候调参数定义得太含糊模型生成了非法参数工具一调就报错。我后来在每个参数里都写清楚格式、边界条件和示例值调用成功率立刻上了一个台阶。第二个是记忆管理。Agent 需要记住“用户刚才说了什么”“自己前面做了什么”。短期记忆通常就是对话上下文但上下文一长就会把模型输入窗口撑爆所以要做摘要和裁剪把旧对话自动压缩成一段摘要再拼接当前的最近几轮。长期记忆则要靠外部存储比如把用户偏好、历史任务结果向量化存入向量库在需要时检索出来。这对工程的要求不低但场景越复杂这套东西越省不掉。第三个是状态与迭代控制。Agent 如果让模型无限循环推理下去轻则浪费 Token重则陷入死循环。我必须在工程侧画一条硬边界最大步数设一个值超过就强制结束单轮工具调用超时也设一个超时控制器防止某个外部接口一直卡住。4.3 真实世界里的 Agent 最容易翻车的地方我试过让一个 Agent 自动处理“用户退款”的流程。第一步是查询订单第二步是校验退款资格第三步是发起退款。看起来简单但实际操作中出现过一个非常典型的问题查询订单的接口因为上游网络抖动返回了超时Agent 没有做任何重试策略直接把超时当成了“订单不存在”接着告诉用户“没有查到相关订单退款无法处理”。这个问题的本质是Agent 把“工具调用失败”当成了“业务结果为不存在”。两种状态在业务语义上完全不同但模型在默认情况下没有这个概念。解决方式是在工具返回结构里加上状态码和明确的错误信息同时在推理阶段用约束告诉 Agent如果工具本身报错必须重试或明确告知系统异常绝不能直接跳到业务结论。这个坑是真实业务 Agent 最容易翻车的地方。再加一个工程细节流式输出。我用 SSE 往客户端推流的时候Agent 每一步推理和工具调用过程都需要推给前端用户才能看见“正在查询订单…正在校验资格…”这些过程。这个过程不能用一次性返回否则体验会非常奇怪。5. 评测与可观测把“感觉还行”变成“有证据”5.1 没有评测集一切优化都是玄学“我感觉回答变好了”这大概是 AI 项目里最危险的自我欺骗。没有评测集你就无法判断是 Prompt 改得更好了还是模型换对了还是今天运气好。我自从开始做 AI 工程后养成的习惯是任何项目开工第一天就先花时间建一个小型评测集。评测集的来源很简单从真实业务日志里挑最近高频的问题加上同事互测时提的刁钻问题覆盖正常情况、边界情况和完全无解的“垃圾问题”三类。正常情况要 60% 左右边界情况 30%完全没有答案的问题也要留 10%——因为系统必须学会说“我不知道”不能硬编。起步阶段 50 到 100 条足够用后期再按业务模块扩展。我的评测流程通常是两步先跑一轮全量离线评测统计各项指标再把新版本和老版本在评测集上跑一个并排对比人工抽看回答质量。没有这种对比就不要轻易上线“新优化的 Prompt”或“新换的模型”因为效果的不确定性在 AI 系统里远高于传统软件。5.2 LLM-as-judge 的实操细节人工评测质量高但成本也高我只在关键节点上人工看。日常迭代我采用“LLM 作为评委”的方式用一个更强的模型给另一个模型的输出打分。这里有几个关键细节要特别注意。打分 Prompt 必须定义清楚打分维度比如相关性、完整性、引用一致性避免让评委模型凭感觉给分还要给它参考答案让打分有据可依。另一个坑是位置偏差同一个答案放在 A 位和放在 B 位模型给出的胜负结论可能不一样所以两两对比时A/B 两个位置要交换各评一次结论不一致就标记为待人工复核。常用指标我整理成了一张表指标说明评估方式回答准确率回答是否正确人工/LLM judge检索命中率引擎召回的内容是否包含正确答案自动化通过标注数据计算响应延迟从请求到生成完毕的时间压测取 P50/P95Token 成本每次请求消耗的 Token 数从日志统计拒答准确率对于无答案问题是否正确拒绝人工抽查5.3 可观测上线之后你靠什么活着模型部署上线不是终结而是另一种开始。没有可观测性的 AI 系统出了事你都不知道从哪查起。我在服务里集成了一套完整的日志链路记录每一次请求的模型参数、输入输出、Token 用量、检索命中的文档 ID、耗时分布甚至 agent 每一步的工具调用轨迹。排查线上问题全靠这些 Trace。还需要盯的是成本指标因为 AI 项目的成本逃逸速度超出想象。我见过一个团队上线了一个搜索增强功能上线时测着还行一个月后账单翻了十几倍——细查才发现有些 Prompt 越写越长模型输出的 Token 数量也在悄悄膨胀每次请求成本从几分钱变成了几毛钱。成本就是 Token 消耗的积木游戏不监控就像水管漏水等你发现时地板早就泡透了。我在监控面板上常驻四个数字请求量、平均响应 Token 数、总 Token 消耗和每日成本趋势任何一项异常升高第一时间报警。6. 常见问题排查与排查实录6.1 高频问题速查表我把自己项目里反复遇到的问题按“症状-排查思路-解决方式”整理成了一张速查表也分享给你。症状排查思路解决方式显存不够直接 OOM看权重精度、上下文长度、并发数换 4bit 量化、调低max-model-len、限制最大并发用户问法稍一变化就检索不到检查切分质量、Embedding 匹配度重新切分、换领域 Embedding、加同义改写输出结果明显超长检查系统 Prompt 和温度参数显式限制max_tokens、约束格式流式接口响应延迟高看 TTFT、看服务排队情况增加实例、调低gpu-memory-utilization留足并发余量模型对工具返回的错误信息产生幻觉看错误信息是否结构化传入增加明确状态码和错误类型约束模型区分“失败”与“业务空结果”6.2 三个值得分享的独家排查经验第一个经验是关于切分边界的修复。我最早固定按 512 长度切分结果一段讲“权限设计原则”的内容被切成了两半检索出来的永远是“设计原则”的一半永远缺了另一半。当时排查了很久最后把切分日志全部打出来才发现所有边界问题集中在几个固定位置。后来我写了一个自适应切分函数遇到正文中的标题或段落标记先把文档切开再对每个大块做长度检查和是否需要二次分割解决了这类问题。第二个经验是关于 temperature 参数的弹性调整。项目刚上线时我图省事所有场景统一设 0.7结果在检索类任务里模型经常用花哨的说辞填充本应直接引用的原文用户一看就是“在胡编”。后来我把任务类型拆开需要事实精确的任务检索问答、数据提取设 0.1 到 0.2需要生成多样性的任务文案、摘要保持 0.7 到 0.9效果立刻变好。同一个模型不同任务用不同的采样参数是我最推荐的基础优化手段。第三个经验是关于压测的姿势。用简单的curl请求跑一遍压测根本没有意义因为生产的并发模型和真实用户行为完全不同必须用真实数据回放或尽可能接近真实场景的脚本去压测。我第一次做压测只跑了一个循环完全没发现系统在并发达到 16 时延迟陡增等上线后真实用户一拥而上才被打了个措手不及。关于 AI 工程这条路我自己的体会是它跟传统软件工程很像都是在不确定性里寻找确定性。模型是工具箱工程是脚手架真正值钱的能力是在真实系统里组织这些不确定性。如果你现在也在从零开始我的建议是不要一开始就追最前沿的模型和算法先把你手上的模型、数据、推理、检索、评测真正跑通一遍把每一个环节的质量和成本都摸出数来。这套“打通链路”的能力比背上一百个新概念都管用。之后无论模型怎么迭代你手里的这套工程方法论都能换汤不换药地继续发挥作用。
返回列表