尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从零搭建AI工程体系:数据管道、RAG与部署实战

从零搭建AI工程体系:数据管道、RAG与部署实战 先聊个现实问题现在网上铺天盖地都是“AI课程”“大模型实战”但大部分内容要么是API调用演示要么是拿现成模型跑个demo。真到了要自己从零搭一套AI工程体系的时候很多人依然是懵的——数据怎么处理、模型怎么选、评估怎么做、上线怎么部署这些环节之间的耦合关系远比想象中复杂。我见过太多团队模型在notebook里跑得飞起一上生产环境就崩或者是调了三天prompt最后发现是数据清洗环节出了问题。“ai-engineering-from-scratch”这项目名字听着很硬核但本质就是想回答一个问题在大模型时代怎么靠一套扎实的工程方法论把一个AI想法变成真正能跑、能维护、能迭代的系统它适合的读者不是那种只想“玩一玩”的爱好者而是真正要落地AI应用的开发者、技术负责人以及想系统建立AI工程认知的产品经理。这篇文章不会停留在概念层面我会把我自己踩过的坑、验证过的方案、总结出的方法论全部摊开来讲。1. 内容整体设计与思路拆解1.1 搞清楚“AI工程”到底在解决什么问题很多人以为AI工程就是“训练模型”或者“调用模型API”这其实是很大的误解。模型本身只是整个系统里的一个组件甚至不是最核心的那个。我从一个真实的经历说起去年有个朋友做了一个法律咨询问答机器人模型用的是市面上很成熟的开源大模型prompt也精心调过demo演示效果非常好。但一进入小范围测试就出问题了——用户问的问题稍微带点口语化比如“我借钱给朋友他现在不还我能告他吗”模型就开始胡说八道。后来排查发现问题的根源不在模型而在数据管道。这个例子暴露了AI工程的核心矛盾模型能力只是天花板而工程能力决定了你能摸到多高。数据管道、评估体系、推理优化、监控反馈这些环节才是决定一个AI应用能否稳定运行的基石。没有坚实的工程底座再强的模型也就像一台没有方向盘的跑车速度越快越容易出事。我理解的AI工程大致可以拆成五个核心模块数据层包括数据采集、清洗、标注、增强、版本管理。模型层包括基座模型选型、微调、量化压缩、推理优化。评估层包括离线评估指标、在线测试集、用户反馈回收、回归测试。架构层包括RAG检索增强生成系统设计、Agent编排、工具调用、记忆管理。运维层包括部署方案、监控告警、日志追踪、模型灰度更新、成本控制。这五个模块不是孤立的它们之间存在强烈的依赖关系。数据质量决定模型效果上限评估体系决定迭代速度架构设计决定系统复杂度边界运维能力决定应用能否长期稳定运行。从零开始做AI工程最忌讳的就是一头扎进某个模块结果发现自己陷入局部最优整体系统反而跑不通。1.2 为什么强调“from scratch”以及它的学习路径设计逻辑“from scratch”这个词在技术圈已经有点泛滥了很多标榜“从零开始”的教程实际上还是让你在一个已经搭好的框架里做填空题。但这个项目的特殊之处在于它强调的是不依赖任何黑盒工具把AI工程的最小必要模块从头实现一遍理解每个环节的内部机制然后再引入成熟的工具链。为什么一定要这样做我举个很直观的例子现在很多开发者用LangChain或者LlamaIndex搭RAG应用觉得特别方便几行代码就能把文档灌进向量库然后做问答。但一旦遇到检索效果不好他们往往连排查的抓手都没有——不知道是分块策略的问题、embedding模型的问题还是top-k参数的问题。而如果你自己写过一个最简单的RAG流程亲手实现过文本分块、向量化、相似度检索这几个步骤你就能在几分钟内定位到瓶颈所在。项目推荐的学习路径大致分四个阶段基础能力构建Python工程化能力、深度学习基础、LLM核心概念token、context window、attention机制等。经典AI工程模块复现用原生代码实现数据处理管道、一个最小可用的RAG流程、一套模型评估框架。系统化整合把前面实现的模块串起来搭建一个完整的AI应用后端引入工作流引擎、任务队列、缓存机制。进阶与精进引入高并发服务、模型微调、Elasticsearch或专业向量库、可观测性体系对标企业级AI工程实践。这种路径设计背后有一个重要的理念先会手动造轮子再学会用轮子。只有当你亲手实现过相似度检索才能真正理解向量数据库里的HNSW索引、IVF索引到底在优化什么只有当你手动一行行写过评估脚本才能真正理解RAGAS这类评估框架为什么要设计那些指标。这种“知其所以然”的认知深度决定了你在面对复杂生产问题时能走多远。2. 核心细节解析与实操要点2.1 数据管道里最容易被忽略的三个环节数据是AI工程的地基但也是最枯燥、最不容易出成就感的部分。我见过太多团队在这个地方翻车用三个字总结就是脏、乱、粗。具体来说有三个环节经常被忽略但它们恰恰决定了模型效果的上限。第一个是数据版本管理。代码有Git管理但数据往往散落在各个目录、各个同事的电脑里甚至存在网盘上。等模型效果出现波动你想回溯“之前那个效果好的版本用的到底是什么数据集”结果所有人各执一词这就是典型的灾难场景。我建议在最开始就引入DVCData Version Control或者LakeFS这类工具给每个数据集打上版本标签并且和代码提交记录关联起来。做这件事的投入产出比极高——平时感觉不到它的存在一旦需要回溯排查它就是你的救命稻草。第二个是数据清洗的规则沉淀。很多人清洗数据是一锤子买卖在notebook里写一坨正则表达式跑一遍就完事完全没有把清洗逻辑沉淀成可复用的模块。正确的做法是把清洗流程拆成独立的组件比如去重模块、去敏感信息模块、格式标准化模块并且为每个模块写单元测试。我在一个实际项目里遇到过一个让人崩溃的问题——某天突然发现模型输出的格式全乱了怎么调prompt都没用最后才发现是上游数据集里混入了几条没有经过格式清洗的样本把few-shot示例的分布彻底带偏了。第三个是长文档的分块(chunking)策略。这是做RAG系统时最容易被低估的环节。很多教程告诉你“按固定大小分块”比如512个token切一刀但真实场景里这么做往往效果稀烂。文本分块要考虑语义完整性代码要按函数和类来切技术文档要按标题层级来切小说要按段落和对话来切。我常用的一个技巧是先做结构感知的预切分再根据embedding的相似度做递归合并让每个chunk内部的语义尽量内聚。这块没有银弹只有反复实验和调优。2.2 模型选型和微调的实用决策思路模型选型没有标准答案但绝对有标准决策框架。我的个人经验是不要一上来就看指标榜单而是先做一个简单的约束分析列四个问题推理成本上限是多少延迟要求是多少上下文长度要求多少领域专业度要求多高比如你做的是一个面向C端的聊天助手那可能牺牲一些效果也要选一个推理速度快的轻量模型把成本压在可控范围内但如果是面向金融行业的文档抽取系统那准确性就是第一优先级即使推理慢一点也可以接受毕竟一个字段抽错了带来的损失远大于GPU算力成本。关于微调我想强调一个重要认知能用prompt工程和RAG解决的尽量不要微调。这不仅是成本考量更是维护性考量。Prompt和RAG是“软编码”改起来只需要更新文本和索引微调是“硬编码”改一次动辄要重新训练和评估。除非遇到了两种情况——模型对某个领域的专业表述理解严重欠缺或者模型输出的格式无论如何都无法被约束——否则不建议走向微调这条路。如果确实需要微调的我的建议是从参数高效微调PEFT开始比如LoRA。因为全参微调不仅成本高昂而且很容易发生灾难性遗忘把模型原本具备的通用能力洗掉了。我自己踩过最大的一个坑是为了提升模型在“电商评论情感分析”上的准确率把全参微调跑了一轮等模型上线了才发现它连“今天天气不错”这种基本句子的情感都判断不准了。后来换成LoRA之后问题才彻底解决而且训练时间从几天直接缩短到了几个小时。2.3 评估体系设计别被“感觉还行”欺骗AI工程里最可怕的是“感觉还行”。模型效果好不好不能靠人肉抽样看几个case也不能只看loss曲线下降就认为大功告成。我在实际项目中吃过这个亏有一版模型离线评测的BLEU分数涨了10个点我满心欢喜地上线结果用户反馈极差模型生成的文本表面看着流畅实则寄生在训练集里抄了近似的句子。这种“评测指标虚高、实际效果拉胯”的错位根源就是我当时只关注了自动化指标没有建好评估闭环。一个可靠的评估体系至少要有三层单测级评估一组固定的、覆盖核心场景的最小评测集每次迭代模型或prompt都必须跑一遍保证质量不回退。离线批量评估一个较大的评测集涵盖正常样本、边界样本、异常样本用多个维度准确率、相关性、忠实度、格式合规性计算综合打 分。在线反馈回收线上用户对模型输出的点赞/点踩、复制、重新生成等行为数据回流到离线评估集里形成反馈飞轮。这个三层体系里面每一层都有它的存在价值。单测级评估保证的是“不倒退”离线批量评估保证的是“能变好”在线反馈回收保证的是“符合真实需求”。缺少任何一层都会让你的迭代过程变得盲目。特别是第三层我建议每个AI应用在第一天就埋好反馈数据回收的接口哪怕一开始只在页面上加一个简单的“赞成/反对”按钮也会在后期爆发出巨大的作用。我曾经做过一个AI客服系统表现最好的那个版本并不是离线指标最高的版本而是用户点踩率最低的版本。其中一个指标隐藏着值得注意的规律用户面对冗长的标准答案时即使回答内容完全正确点踩率也比简洁但略不全面的答案高。这个规律完全依赖线上反馈才能发现如果只盯着离线指标大概率会把产品带偏。3. 实操过程与核心环节实现3.1 从零搭建一个最小可用的AI应用以“企业知识库问答Bot”为例这部分我用一个具体的案例来演示从裸机环境开始搭建一个“企业知识库问答Bot”。它需要读取公司内部的制度文档、操作手册能根据员工提问给出带来源引用的回答。这个案例覆盖了AI工程的核心链路数据处理、RAG流程、评估指标、服务化部署而且对硬件要求不高用普通开发机加少量GPU卡就能跑通。整个项目我拆成了六个步骤每个步骤都有明确的产出物和验证方式。第一步环境与基础设施准备操作系统层面Ubuntu 22.04是最稳妥的选择。需要预装Python 3.10、CUDA工具包如果用GPU推理、Docker用于隔离环境。另外建议用Miniconda管理Python环境不要直接往系统里装包防止依赖冲突把机器搞得一团糟。我见过太多开发者在这个环节就翻车环境冲突耗掉一整天。第二步文档采集与清洗假设我们有2000份PDF和Word格式的制度文档。先用工具批量转成纯文本推荐Apache Tika或者Pandoc处理步骤中要对每个文件做编码检测避免中文乱码。转换完成之后做统一清洗去掉页眉页脚、去除多余换行、修复断行、统一标点符号。这里要注意的是清洗规则一定要一套写死并统一执行不要让团队各写各的不然后续合并数据时会出现系统性差异直接影响检索结果。第三步文本分块与向量化分块策略这里我使用的是“结构感知递归合并”的方案先用正则把文档按照标题层级拆成小节如果小节内容过长再按段落切分最后按embedding相似度合并相近的小块。分块之后用BAAI/bge-large-zh-v1.5做向量化这个模型在中文场景下性价比很高且支持通过标题和正文拼接来提升检索精度。向量化之后的向量维度是1024维存入本地向量数据库之前需要统一转为numpy数组格式。第四步搭建向量检索服务向量数据库我推荐用Milvus或者Qdrant它们在百万级数据量下的检索延迟都控制在几十毫秒。初始化逻辑很简单连接collection定义字段文本id、文本内容、向量、元数据然后创建HNSW索引索引参数按文档数量调整文档数量在10万以下时M设为16efConstruction设为200文档数量在10万以上时M设为32efConstruction设为500。检索时的ef搜索值设为64保证召回率与延迟的平衡。这一步看似不起眼但索引参数直接决定检索效果。有一次我把efConstruction设成了32结果十万级数据下的召回率掉了接近一成肉眼看起来就是“答案找不到”或者“答案张冠李戴”。调索引参数时必须跑一批评测集去验证效果不要想当然。第五步搭建RAG工作流工作流逻辑如下接收用户query用向量模型转成向量。在向量库执行相似度检索取top-k个候选chunkk初始设为5。对候选chunk做重排序可选如果引入bge-reranker可以显著提升排序质量代价是每个query需要多花几十毫秒。将候选chunk与自身的system prompt拼接送进大模型生成最终答案。prompt模板我用的是这种风格你是企业内部的智能问答助手。请基于以下资料回答问题。如果资料中没有相关信息请直接说“根据现有资料无法回答”不要编造。 资料 {context} 问题{question}这里最核心的一个技巧是prompt里显式地要求模型在信息不足时直接承认不知道。因为RAG系统最让人头疼的幻觉问题往往不是模型能力不够而是模型在信息不足时依然强行作答。加了一句“不要编造”看似简单却能把幻觉率降低一大截。第六步部署与监控部署方案我建议先把整套系统打包成Docker镜像内部拆两个容器一个跑FastAPI接口服务一个跑向量数据库。用docker-compose编排对外暴露8000端口。监控方面至少要采集三个指标响应延迟、检索命中率、用户点踩率。其中检索命中率是RAG系统最关键的指标之一它反映的是“系统有没有找到正确的参考文档”如果这个指标偏低说明分块或embedding方案肯定有问题。3.2 关键代码片段与参数取舍说明下面直接给出核心代码。第一个是分块函数import re from typing import List def smart_chunking(text: str, max_tokens: int 500, overlap: int 50) - List[str]: # 先按标题层级切分 sections re.split(r(?m)^(#\s|\d\.\s|[一二三四五六七八九十]、), text) chunks [] for i in range(1, len(sections), 2): heading sections[i] body sections[i1] if i1 len(sections) else content (heading body).strip() if not content: continue # 分段重叠逻辑 if len(content) max_tokens: chunks.append(content) else: current for paragraph in content.split(\n\n): if len(paragraph) max_tokens: for j in range(0, len(paragraph), max_tokens - overlap): chunk paragraph[j:jmax_tokens] if chunk.strip(): chunks.append(chunk.strip()) elif len(current) len(paragraph) max_tokens: current \n\n paragraph else: chunks.append(current.strip()) current paragraph if current.strip(): chunks.append(current.strip()) return chunks这个函数的核心思路是结构切分保证语义边界段落合并保证上下文完整滑动窗口保证长段落不溢出。overlap参数的作用是防止切分点正好把关键信息拦腰截断但这个参数也不是越大越好过大的overlap会让相邻chunk重复太多检索时会丢失区分度。第二个是RAG查询链路from milvus import Collection from sentence_transformers import SentenceTransformer embedder SentenceTransformer(BAAI/bge-large-zh-v1.5) collection Collection(knowledge_base) collection.load() def retrieve(query: str, top_k: int 5): q_vector embedder.encode([query], normalize_embeddingsTrue)[0] results collection.search( data[q_vector], anns_fieldvector, param{metric_type: IP, params: {ef: 64}}, limittop_k, output_fields[text, source], ) return [{text: hit.entity.get(text), source: hit.entity.get(source), score: hit.score} for hit in results[0]]这里的相似度计算用了内积IP而不是余弦相似度。原因是bge系列的模型在训练阶段已经对向量做了归一化内积和余弦在数学上是等价的但内积计算的延迟和CPU开销略低。这套写法在生产环境实测很稳是我推荐的标准RAG查询写法。3.3 生产化落地版本管理、性能优化与灰度发布一个AI应用从demo到生产环境中间还有很多提升稳定性的细节要做。我在实际项目中遇到的最痛的教训之一就是线上模型突然“变笨”了——最后排查出来的原因不是模型被改动了而是依赖的向量库数据被某人误操作清掉了。这件事让我意识到必须在整个流程中加入版本管理意识。数据层面我给知识库的每次更新都打了一个版本号向量集合的命名里带上版本后缀比如“knowledge_base_v20240315”。代码层面模型和embedding的版本都固定在requirements.txt或模型注册表里禁止随意升级。上线层面的流程我用的是金丝雀发布灰度发布策略先让新版本模型处理10%的流量观察点踩率和延迟指标连续24小时稳定后再逐步扩展到50%、100%。整个过程配合日志追踪能快速精准定位异常请求发生在哪个环节。性能优化这块我为FastAPI服务加了一层LRU缓存把高频重复的问题直接命中缓存返回结果整个服务的平均延迟从1.2秒降到了300毫秒而缓存击穿问题由信号量锁解决。这种性能优化的经验一般教程里不会详细讲但在真实生产环境里它就是服务稳定性的分水岭。4. 常见问题与排查技巧实录4.1 RAG系统三大经典故障及排查流程做RAG系统这一年多我总结出三类最高频的故障以及对应的排查思路。故障一检索到的文档和问题不相关。这是最多发的故障。排查步骤可以按“数据→分块→向量→检索参数”四层依次推进。先看原始文档是不是覆盖了query涉及的知识点再看分块后的chunk是否保留了语义完整性然后用embedding模型跑几个相似句子对做自检最后检查检索参数ef、top_k、距离度量方式是否合理。故障二答案看着对但来源文档里根本没有。这种情况说明模型产生了事实幻觉。优先检查prompt里有没有“如果没有资料支撑直接说明无法回答”的兜底指令其次检查temperature参数是否过高建议先调到0.1~0.2。如果还有幻觉就要考虑在当前工作流里强行加入“引用验证”环节比如用正则从回答里提取关键实体去和来源文档比对不一致就触发重新生成。故障三检索正确但答案生成不符合预期。比如用户要简洁答案模型却长篇大论用户要表格模型却给列表。这种问题通常不在模型而在prompt的指令不够明确以及评测集里缺少格式偏好的标注。建议在prompt里给一两个强格式few-shot示例或者改用更结构化的输出约束方式如JSON schema约束。4.2 排查工具与信息追踪我一直强调一个观点AI工程想要快速排查问题就需要观测工具覆盖“模型输入→中间结果→最终输出”的全链路否则你很难判断问题出在哪一层。我自己的做法是在关键节点之间插入Trace记录至少包含以下信息用户的原始query内容。向量检索返回的top-kchunk及其相似度分数。最终送入模型的prompt全文。模型返回的原始输出。后处理的格式化内容和耗时。有了这些记录排查问题时就能精准复现链路而不是靠猜。尤其注意类似“逆代”这种不确定性输出在你没有完整链路记录时几乎不可能定位问题。关于向量检索工具选型这里也给出一个直观的对比表方便大家根据场景决策工具部署方式适合数据量核心优势主要短板FAISS嵌入式需自研服务百万级以下轻量、部署简单、CPU跑得动无分布式、故障恢复难Qdrant独立服务/Docker千万级Rust性能好、过滤能力强占用内存偏高Milvus独立分布式亿级功能全、生态强、支持混合检索组件多、运维门槛高Elasticsearch向量插件独立服务千万级已有ES可复用兼顾全文检索向量性能弱于专用库我个人在小规模场景用FAISS快速验证非常舒服到了生产环境更推荐使用Qdrant或Milvus。如果团队已经有ES维护能力用ES的向量检索能力也是一个务实的选择。4.3 成本优化与上下文窗口管理最后聊一个所有AI工程团队都绕不开的话题成本。大模型的API调用成本是按token算的而RAG系统天然有“大量文本塞进上下文”的毛病。我见过非常夸张的案例一个简单的问答请求因为chunk合并策略没控制好一次调用居然消耗了2万多个token成本贵得离谱。我的优化思路分为三步动态调整上下文长度根据问题的复杂度决定塞入的chunk数量简单问候类问题用2个chunk就够复杂分析类问题才用满top-5。用摘要代替原文对于超长chunk先用一个轻量模型做摘要把摘要存入向量库检索命中后再决定是否拉取原文。这能大幅降低存储和调用成本。嵌入端侧缓存把用户问题和答案成对缓存完全相同的query直接命中缓存不为重复流量付费。上下文窗口管理这块还有一个容易被忽略的点模型的上下文窗口是有限的但就算没超限塞入太多无关内容也会让模型“分心”回答精度下降。上下文越短答案越准这个规律在我做过的所有AI应用里几乎都成立。所以做RAG系统时建议始终坚持一个原则能塞3个chunk解决的问题绝不要塞6个。5. 学习路线与进阶方向建议5.1 给零基础者的分段学习规划AI工程的知识面很宽如果没有一个清晰的路线图很容易陷入“什么都学、什么都学不精”的困境。我结合自己从算法转工程、再转AI工程的经验整理了一条分阶段的学习路线每个阶段都有明确的产出物作为里程碑。阶段一Python工程能力筑基2-4周任务列表包括熟练使用Python的数据类、装饰器、生成器、上下文管理器。懂虚拟环境和依赖管理。会用pytest写单元测试会用logging而不是print来输出日志。这些基础技能决定你后续写AI工程的代码是“能跑”还是“能维护”。阶段二LLM基础原理扫盲2-3周理解tokenization、embedding、transformer架构、attention机制的直觉含义。能够回答诸如“为什么大模型是逐字生成的”“temperature参数改变的是什么”这类问题不需要会手推反向传播但一定要建立正确的直觉模型。阶段三核心模块复现4-6周任务包括用纯Python写一个文本分块工具、用sentence-transformers实现一个向量检索流程、用FastAPI封装一个模型接口、写一套评估脚本计算准确率和召回率。这个阶段的目标是“补全AI工程的基本肌肉记忆”所有代码自己动手敲进去不要复制粘贴。阶段四系统整合与进阶6-10周把前面的模块串起来做一个完整的项目比如知识库问答Bot、AI客服工作台。引入Docker、向量数据库、缓存机制和监控告警。有能力面对“检索不准、回答幻觉、接口超时”这三座大山并独立完成至少一轮系统级优化。5.2 持续进阶的三个方向完成基础路线之后你就要根据自己的实际业务方向做技术深耕。我目前看到的AI工程进阶方向大致有三条方向一RAG与搜索深度优化。深入语义分块、reranker模型、混合检索关键词向量、多路召回等技术。适合做企业知识管理、智能客服、搜索引擎的开发者。方向二Agent与多智能体协同。研究Agent的规划能力、工具调用机制、多Agent协作框架反思、规划、执行等模式。适合做自动化工作流、复杂任务拆解的场景。方向三模型推理与服务化优化。聚焦vLLM、TensorRT-LLM、量化推理、批处理策略等高性能推理技术。适合做模型服务基础设施、大并发AI平台方向的工程师。5.3 学习过程中牢记的三个认知第一AI工程能力不是靠看教程看出来的是靠调试真实故障调出来的。我在学习过程中最受益的环节不是某门课而是亲手把一个还没搞懂的RAG流程跑通、跑挂、再跑通的过程。那种对系统各个组件“脾气”的理解完全是经验型知识。第二时刻给自己找“陌生问题”。如果发现自己在某个阶段顺风顺水说明你该换一个更有挑战的项目了。“AI工程能力成长最快的时候就是你发现自己以为懂了但其实并没有懂的时候。”p第三从第一天就做好记录。我强烈建议为自己的每个项目建一份工程日志记录关键决策、踩坑过程、参数组合和效果变化。这不仅是为了沉淀经验更是为了在半年后回头看时能一眼看出当时决策的得失。写在最后回到开头说的那个法律咨询机器人。后来我们团队系统性重建了数据管道设计了完整的评测集还把推理链路里的每一步都盯死了。最后模型本身没有换但效果却有了质的飞跃。这件事给我的启发是AI应用效果的差距很多时候不是模型的差距而是工程体系的差距。“ai-engineering-from-scratch”这个项目的价值就在于此——它跳过了花哨的概念直接指向了AI落地最核心的那些工程问题。数据怎么管、RAG怎么做、评估怎么建、故障怎么排、成本怎么控这套完整的方法论在当前大模型野蛮生长的环境下反而是稀缺品。我个人在实际训练和部署AI应用过程中最大的体会是永远要敬畏工程复杂性。模型是天才策略家但工程是严苛的交付者。希望这篇拆解能给正在做AI工程的朋友带来一点启发。如果你也在这条路上摸爬滚打欢迎在实践中一点点打磨自己的体系踩过的坑都会变成你未来最快的路。
返回列表