从零开始学AI工程:以RAG文档问答贯穿全流程的实战路线

发布时间:2026/11/3 6:03:20
从零开始学AI工程:以RAG文档问答贯穿全流程的实战路线

过去一年里,我被问到最多的问题不是某个具体模型的效果如何,而是那句重复了无数次的疑问:“我想从零开始做AI工程,到底应该先学什么?”

问这个问题的人,有刚毕业的学生,有写后端、前端遇到瓶颈的工程师,也有已经在算法岗位做了几年却始终觉得自己在“炼丹”的同事。每次我都先反问一句:你说的AI工程,是会调用几个模型接口,还是能独立把一整套AI产品从想法带到上线、再持续迭代?

如果你想要的是后者,这篇文章就是为你准备的。它不是某个课程的浓缩笔记,而是我从零开始走通AI工程这条路的完整复盘。我特意选了目前最典型的“文档问答(RAG)”作为贯穿案例,因为它几乎覆盖了AI工程项目的所有关键环节:数据分析与清洗、模型接入、检索设计、评测、部署上线、监控迭代。把这些环节走一遍,你就能理解AI工程真正在解决什么问题,以及为什么它和单纯跑通一个Notebook完全是两码事。

1. 拆解“AI工程师”这个角色:为什么我说它既不是调包侠,也不是炼丹师

很多人在入门之前,对AI工程师的工作想象只有两类:一类觉得是调API、调包,另一类觉得是天天读论文、调超参。实际上,AI工程师夹在中间,做的是把模型能力变成产品能力这一整条链路。

1.1 一个让我彻底改变认知的工作场景

我在带第一个AI项目时,算法同事交付了一个线下准确率非常高的分类模型。演示的时候,一切都很完美。但真正要把这个模型放到生产环境里,我遇到的第一批问题根本和模型本身无关:训练数据里有大量空值和重复样本,线上请求的字段格式和训练时不一样,模型返回结果的时间不稳定,还有用户输入从来没有出现在训练集里的内容时,系统直接给了个莫名其妙的答案。

那一刻我才意识到,AI工程的重点不在“让模型准确率高一个点”,而在“让模型在一个充满意外、不可控、持续变化的环境里仍然可靠”。从那以后,我再也不把“调模型”当成AI工程的全部。

1.2 AI工程师、算法工程师、数据科学家:三张不同的任务清单

这三类角色经常被混在一起说,工作内容差异其实很大。我用一张表给你做个对比:

角色主要产出评判标准典型工作内容
算法工程师模型、实验报告离线指标:精确率、召回率、AUC设计网络结构、调超参、读论文、做对比实验
数据科学家分析结论、报表、业务洞察业务认知的增量取数、清洗、统计分析、AB实验设计
AI工程师可上线、可维护的AI系统在线指标、稳定性、成本、迭代速度数据管线、模型接入、评测体系、部署监控、badcase反馈闭环

算法工程师追求的是“在给定数据集上做出最好的模型”,AI工程师追求的是“让系统在真实用户手里持续可用”。前者像在实验室里研究一道菜的极限口感和营养价值,后者像经营一家每天要稳定出几百份餐的中央厨房——原料会缺、订单会变、厨师会请假,你都得兜住。

1.3 AI工程独特的地方:概率输出与数据漂移

传统软件开发里,函数的输入输出是确定的:传入一个整数,返回处理后的字符串,逻辑可预期。AI工程完全不同,模型输出带有概率性,同样的输入,今天和明天的答案可能不一样。更麻烦的是,数据本身会漂移:用户说话的方式、业务规则、内容形态都在缓慢变化,去年效果很好的模型,今年可能悄悄变差。

所以AI工程必须额外做三件传统开发不太需要做的事:建立评测基准,持续监控输入分布和输出质量,设置兜底与降级策略。这些事占了整个工程投入的一大半,却几乎不会出现在模型论文里。

想清楚这些之后,你再看“from scratch”这件事,思路就会不一样:缺的不只是某个模型的调用方法,而是一整套把想法变成可靠系统的工程方法论。

2. 从零制定的三条主线:为什么我没有让你先学三个月数学

很多“从零开始学AI”的路线图,第一站永远是线性代数、概率论、微积分。这个方案理论上是正确的,实践上却劝退了绝大多数人。我见过太多人卡在这里:学了三个月数学,连一次像样的模型都没跑过,最终认定自己不是这块料。真相不是不适合,而是学习顺序错了。

2.1 别从数学开始,从“能跑通”开始

我做了一个比喻帮你理解:想学会做饭,最好的办法是先按菜谱做出第一道能吃的菜,知道咸淡是什么回事;而不是先从“热力学第一定律”学起,搞明白火焰传热的原理再动手。数学对AI很重要,但它解决的是“为什么”的问题,而“能跑通”解决的是“我能做到”的问题。

没有正反馈的学习,很难坚持。一次“我能跑通”、看到输出结果的体验,比一百页公式推导更能给你继续下去的动力。数学知识可以在遇到具体问题时按需补,带着问题去学,效率远高于漫无目的地啃教材。

2.2 三个阶段的目标、动手内容和检验标准

我把从零到能独立做AI工程的路径,拆成了三个阶段。每个阶段的产出都是可验证的,不会让你陷入“学了但不知道自己会不会”的状态。

阶段目标动手做什么阶段检验标准
阶段一掌握数据处理的基本感用Python读取一份真实数据,做清洗、统计、可视化,跑通一个简单的分类或回归任务能独立完成“读取数据→处理→建模→评价”的闭环
阶段二掌握大模型应用的基本链路用你手上可用的模型API,搭一个最小应用,比如聊天机器人、文档问答或批量摘要工具能把一个脚本封装成接口,让另一个人真的使用它
阶段三按需补原理,走向规模化根据项目实际需要学习线性代数、概率统计、训练微调原理,探索检索优化、评测体系、成本控制能对已有系统做系统性评测并提出改进方案

阶段一用到的工具很固定:Python基础语法、pandas处理表格、matplotlib或pyplot画图。不要贪多,不要一上来就学各种高级框架。你只需要体会到“数据是可以被程序理解、处理、分析、预测的”,这个阶段就算达标了。

阶段二最核心的并不是某个框架,而是理解一条链路:输入怎么构造、模型怎么调用、输出怎么解析、异常怎么处理、成本怎么估算。现在的模型服务基本都提供兼容接口,换任何一个平台,调用结构都大同小异。你把一个链路跑透,迁移成本很低。

阶段三则有点像打游戏时回头补技能点。比如你想做微调,就需要理解梯度下降、过拟合、学习率这些概念;你想优化检索,就需要理解向量空间、余弦相似度、倒排索引。这些知识不是一上来就要学完的,而是你要用到时再系统补。

2.3 我判断“可以进入下一阶段”的信号

判断标准不需要外界给,你可以自己检验。阶段一结束时,你拿到一份脏数据不会发怵,知道用什么步骤去处理;阶段二结束时,你给别人演示的不是一个自己电脑上能跑的脚本,而是一个别人也能访问、也能用的服务。有了这两条,你已经比那些“背了一堆模型名词却写不出代码”的人踏实得多。

我见过不少人在阶段一停留太久,觉得必须把Python学到精通、把所有库都背下来才敢开始。没必要,Python学到能处理数据和写函数,就够支撑你进入下一个阶段了。你的目标不是成为语言专家,而是尽快拥有“跑通一条链路”的体感。

3. 从想法到能跑的代码:文档问答机器人MVP搭建实录

理论说再多,不如跑一次。下面我带你走一遍RAG文档问答的最小可行版本(MVP)。MVP的意思是:用最简单的实现,跑通完整链路,先看到结果,再谈优化。

3.1 先把问题定义清楚:这一步占了40%的工程质量

技术人最容易犯的错是一上来就写代码。我先问你几个问题:这个系统给谁用?用户会怎么提问?答案的评判标准是什么?要不要附出处?第一个版本里可以不做但后期必须补的东西是什么?

我用的是给团队搭“内部知识库助手”这个场景。问题范围划定为:用户用自然语言提问,系统从给定的文档库中检索相关内容,生成一段带出处的回答。第一版明确不做:权限隔离、多轮对话、多模态输入。把范围定窄,你才能快速走完全程,建立整体认识。

3.2 模型、向量库与Embedding模型的选型思路

MVP阶段的选型原则只有一个:用最简单、最顺手、最便宜的方案把链路跑通。我当时的选型是:

  • 大模型生成:调用你手上现成的模型API(OpenAI兼容接口或其他平台均可)。MVP阶段不要自训模型,成本高且没必要。
  • Embedding模型:选一个对中文友好的向量模型,比如BAAI的bge系列。它把文本变成向量,用于后续相似度检索。
  • 向量库:先用本地可跑的轻量级工具,比如Chroma。等数据量大了再考虑更重型的数据库。

你可能会问,为什么RAG需要向量库?你可以把向量库理解成一个“擅长做近似匹配的图书管理员”。用户提问题,管理员把问题也转换成向量,在库里找出与问题语义最接近的若干段落。直接让模型阅读整本手册再回答,成本高、速度慢,而且超出上下文窗口时根本无法工作。向量库的存在就是为了在瞬间把范围缩小到最相关的几段。

3.3 从切分到生成的完整代码链路

我把核心代码拆成四步,每一步都对应一个明确目的。这份代码不是生产级方案,而是让你看清流程。

import os from pathlib import Path from langchain.text_splitter import RecursiveCharacterTextSplitter # 第一步:读取文档并切分 doc_text = Path("docs/manual.txt").read_text() splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 每个片段约500字符 chunk_overlap=50 # 片段间重叠50字符,避免切断关键语义 ) chunks = splitter.split_text(doc_text)

切分这一步很关键。如果chunk太小,检索到的内容会缺乏上下文;太大,又容易混入无关信息。500字符加50重叠是经验起点,后期要用评测集来验证调整。

# 第二步:向量化并写入向量库 import chromadb from sentence_transformers import SentenceTransformer model = SentenceTransformer("BAAI/bge-small-zh-v1.5") client = chromadb.Client() col = client.get_or_create_collection("docs") col.upsert( ids=[f"chunk-{i}" for i in range(len(chunks))], documents=chunks, embeddings=[model.encode(c).tolist() for c in chunks], )

向量化的作用相当于给每个片段生成一组“语义指纹”。之后来一个问题,系统先计算问题的语义指纹,再去库里找指纹最接近的几个片段。

# 第三步:检索相关片段 query = "文档里关于部署环境的要求是什么?" q_emb = model.encode(query).tolist() hits = col.query(query_embeddings=[q_emb], n_results=5) context = "\n".join(hits["documents"][0])

这一步体现了基本版RAG的全部价值:不把所有资料都塞给模型,而是先从库里找出最相关的5个片段,把它们当作回答的“参考资料”。

# 第四步:构造Prompt并生成答案 from openai import OpenAI llm_client = OpenAI(api_key=os.getenv("LLM_API_KEY")) resp = llm_client.chat.completions.create( model="gpt-4o-mini", messages=[ { "role": "system", "content": "请只根据提供的资料回答,资料里没有的信息,直接说明不知道,不要编造。", }, { "role": "user", "content": f"资料:\n{context}\n\n问题:{query}", }, ], ) print(resp.choices[0].message.content)

这段代码里的system提示词不是装饰,它是第一道防线。明确要求模型“不知道就说不知道”,能显著降低一本正经胡说八道的概率。后期我们还会用工程手段进一步限制幻觉,这个后面再说。

3.4 第一批测试:别期待第一次就完美

跑通之后,我建议你做一件很多人不愿意做的事:主动问它刁钻的问题。我当时试了三个:

  • 文档里明确写过的常规问题:“部署环境有哪些要求?”——预期能回答。
  • 多个章节拼起来才能回答的问题:“整个流程一共需要哪些工具?”——预期很可能会漏。
  • 文档里没有的问题:“这个系统能用来做用户画像吗?”——预期应该是拒绝回答,但往往会编。

我接下来看到的结果是:第一类问题基本能答对,第二类经常答不完整,第三类则偶尔会给出“看起来合理但库里根本没有”的答案。不要沮丧,这些问题就是你建立评测集的起点,也是下一章的讨论内容。

4. 从能跑到可靠:喂给模型的资料是怎么决定答案质量的

MVP跑通之后,你很快会对“能跑”这两个字产生新的理解:程序能运行,不代表答案靠谱。我从这一步开始意识到,决定RAG效果上限的往往不是大模型本身,而是你喂给它的资料质量与检索命中率。

4.1 没有评测集,所有优化都是在开盲盒

我见过太多项目,优化全靠感觉:把chunk从500改成200,觉得“好像更精准了”;换了一个Embedding模型,觉得“看起来更聪明了”。如果没有量化指标,你根本无法判断哪个改动真的有效。所以我在MVP跑通后做的第一件事,是花一个下午建立评测集。

具体做法是:准备50到100条问答对,分成三类。

  • 库内高频问题:文档里明明白白写着答案的常规问题。
  • 库内组合问题:答案分散在多个章节里,需要系统自己拼装。
  • 库外问题:文档里完全不涉及的内容,用于检验系统是否知道“自己不知道”。

每次改动之后,我都拿这组评测集重跑一遍,统计三个基础指标:正确率(答案内容是否符合资料)、引用覆盖率(答案是否覆盖了问题所需的全部关键信息)、幻觉率(答案中出现资料里不存在信息的比例)。有了这套评测集,优化才从“凭感觉”变成了“看数据”。

4.2 决定回答质量的第一杠杆:文档切分策略

如果说有一个参数对RAG效果影响最大,那就是切分方式。chunk太小的典型问题,是检索命中的片段只触及答案的一半;chunk太大的典型问题,是片段里混入太多无关内容,把大模型的注意力带偏。chunk overlap的作用则是避免一个完整概念被拦腰截断。

另外我给每个chunk补过“元数据”:来源文档名、章节路径、更新时间。比如:

  • 切分时在documents列表里同时写入对应的来源字段。
  • 检索返回时把来源信息一并返回。
  • Prompt中要求答案末尾标注“信息来源”。

这一步看起来简单,实际效果立竿见影。用户看到答案时知道它出自哪里,既增加了信任感,又让后续审计bad case变得容易。在我看来,这不是一个可选项,而是RAG工程的最低配置。

4.3 失败模式的四种姿势:症状、原因与排查思路

用评测集测完,基本所有问题都能归到下面四类。我也附上了我的排查思路:

失败类型现象常见原因排查手段改进方向
检索未命中答非所问,或说“资料里没有”但实际有用户问题和文档用词差异过大;chunk切分不合理打印检索命中的chunk内容,看是否相关增加关键词检索做多路召回,或调整切分策略
信息碎片化答案只覆盖问题一半答案被切散在多个chunk,只召回了其中一段提高chunk_overlap,或放大n_results引入摘要式检索,或者做上下文拼装
幻觉答案听起来合理,但库中无依据模型被prompt“带跑”,或者检索到的文本恰好诱导生成检查是否引用了不相关chunk强制加引用来源,增加“资料无相关信息请拒绝”的提示
截断长答案被切断,或整体回答很泛多个chunk拼接后超过上下文窗口,或相关chunk没排进前几位查看token消耗和实际送入的上下文压缩chunk长度,强化检索排序

这四类问题不是独立的,有时候会组合出现。比如检索命中了不相关的chunk,模型就被带偏,产生幻觉。所以我后来把“检索→组装→生成”看成一个整体链路来调,不单独优化其中一环。

4.4 给答案接上“出处”:对抗幻觉最朴素也最有效的工程手段

如果只允许我加一个功能来降低幻觉,我会无条件选择“引用来源”。实现方法不复杂:在把chunks写入向量库时,给每个chunk配一个唯一的来源标识符(可以是文档路径加章节编号)。检索时把来源标识符和chunk内容一起放入context。最后在prompt里要求模型:回答末尾用编号格式标出依据,格式如“参考来源:manual.pdf 第3节”。如果模型找不到依据,它会被迫在回答里写“资料中未找到相关信息”,幻觉空间被大幅压缩。

加入引用来源之后,我的评测集幻觉率从大约15%降到了4%以下。提高的不只是指标,还有整个系统的可审计性:任何一次回答,用户都能回到原始文档里核验。

5. 上线、监控、迭代:最后三公里才是工程的分水岭

能跑、能答,只是第一关。真正把项目变成产品,需要面对的是部署形态、真实流量的冲击和持续迭代的节奏。很多AI项目死在“演示好用,上线翻车”这一步,因为它们忽略了上线前后的巨大差异。

5.1 让模型变成服务:API封装、缓存与限流

我在上线前做的最重要一件事,是把写满实验逻辑的Notebook封装成一个标准的API服务。目的有三个:让前端和其他系统可以调用;把模型推理从请求线程中解耦;为后续的监控、限流和权限控制提供一个稳定入口。

我通常用同步接口处理常规问答,用缓存减轻重复问题的成本压力。缓存逻辑非常简单:如果用户的问题和之前某个问题的距离非常高,直接返回上一次的结果,不再调用生成接口。实测中,业务场景里重复提问的比例非常高,缓存能把成本压掉三四成。

限流则是保护性措施。模型接口不是无限便宜的,真实的线上流量可能瞬间暴涨。我在API层设置了每秒并发上限,超出的请求直接排队或返回提示信息。宁可让用户稍等,也不能让系统因为突发流量打爆成本预算。

5.2 上线第一周我就遇到的事:真实问题和测试集完全不同

第一次上线后,我最意外的发现是:用户问的问题,和我评测集里准备的问题几乎没有重叠。我以为用户会问“部署环境要求是什么”,实际他们问的是“我把Windows机器接入内网后还需要装什么,之前那份说明为什么没提权限变化”。

这就是数据漂移最简单的形态。你无法在测试阶段预判所有真实问题。解决办法不是试图预判一切,而是建立一套“bad case回放机制”:完整记录每个用户输入的原文、检索命中的chunk、最终生成的回答、用户是否有反馈。线上正常运行的AI系统,本质上是一台“永不停止的评测机”,每一天的请求都在告诉你哪里还不够好。

我建议你至少监控这些指标:

指标含义需要关注的信号
请求量与QPS系统负载与使用热度突增时检查限流,突降时检查接入问题
P95延迟用户感受到的响应速度升高说明检索变慢或生成接口变慢
Token消耗成本最直接的风向标异常上升往往来自无用长上下文
检索命中率检索相关chunk的比例降低说明文档库更新后检索没跟上
引用缺失率回答中没有出处的比例升高意味着幻觉风险变大
用户负反馈点赞/踩、追问“不对”等最真实的信号,应每周复盘

5.3 迭代方向:从单路向量检索到多路召回与重排

有了监控数据和bad case回放,下一步就是系统化迭代。优化RAG首先会被我做成优化检索,而不是换大模型。

第一版是单路向量检索,简单但弱点明显:用户问题中如果出现精确的名词、型号,和文档里的字面表达有出入,向量检索容易漏掉。我的升级路径是“多路召回”:一路仍然走向量语义检索,另一路走传统的关键词倒排索引,专门解决精确匹配问题。两条路各自召回一批候选chunk,合并去重后,再用一个重排模型按相关性排序,只把排名最靠前的chunk送进生成环节。

这套方案带来的提升很直观:评测集的“库内组合问题”正确率从65%提到了82%。技术栈没有变复杂太多,但检索的召回和排序质量都上了一个台阶。

5.4 安全与合规是一条不能省的红线

监控和迭代再优先,也不能越过安全底线。处理内部知识库时,我先做了三件事:数据脱敏(把文档里的手机号、身份证号等个人信息用掩码替换后再入库)、权限控制(不同角色只能访问对应范围的检索结果)、访问日志留存(至少保留90天,用于事后审计)。同时,文档来源标注不仅是为防幻觉,也是为责任界定:如果模型回答出了问题,系统要能追溯到是资料本身的问题,还是检索/生成环节的问题。

很多团队在MVP阶段觉得安全合规拖慢进度,等到要对外发布或面对真实业务数据时,才回头补课,成本高得多。先想清楚再动手,是我的经验。

6. 回望这条路:我个人最舍不得删的三个习惯

走到这里,关于“AI工程从零开始”的方法、案例和参数都已经讲完了。如果让我重走一遍,最值得保留的不是某个具体模型,也不是某个参数配置,而是下面这三个习惯。

第一个习惯:任何改动,先跑评测,再谈优化。我在这上面吃过亏。有一段时间我凭感觉把切分长度从500改成200,自我感觉“答案更精确了”,结果评测集正确率掉了8%。后来我把“先评测再上线”当成铁律,所有优化都必须拿数据说话。

第二个习惯:所有输入输出留痕。AI系统的价值一半在模型,一半在数据。我早期做项目时不注意保存真实用户的问题和答案,等到想改进时才发现没有足够的历史数据做分析。从那以后,我把输入输出日志列为一等公民,它们在未来就是你的评测集和训练集。

第三个习惯:用“链路拆解法”复盘一切事故。用户抱怨答案不对时,我脑子里自动拆成一条链:用户问题→解析→检索→上下文组装→模型生成→返回。每一步都可能出错。先通过日志定位是检索没召回,还是模型没按提示词执行,再针对环节修。这个习惯让我不再慌慌张张地乱调参数。

如果让我用一种特别朴素的方式回顾这段经历:AI工程从零开始,从来不缺资料、课程和工具,缺的是一种“把系统当作一条时刻需要照料的管线”的觉悟。模型只是其中一个环节,如何定义问题、准备数据、评测结果、掌控上线、持续迭代,才是真正决定一个AI项目能走多远的东西。少一些对“新模型、新框架”的追逐,多一些对工程细节的耐心,你会走得更稳,也走得更远。