看到ai-engineering-from-scratch这个标题,我第一反应是熟悉——这不就是我自己过去一年半走过的路吗。从完全不会写代码,到能独立把一个大模型应用从零搭到上线,中间踩过的坑、推倒重来的代码、凌晨三点还在调评测集的经历,几乎全在这个标题里了。如果你正打算进入 AI 工程这个领域,或者已经入行但总觉得底子不牢,这篇文章就是按我的真实路线整理的,每一步我都会告诉你为什么要这么做、当时我踩了什么坑,以及有哪些可以让你少走几个月弯路的实操方法。
这个领域现在最不缺的就是课程和速成教程,缺的是一个人用工程思维告诉你:什么时候该学什么、学到什么程度算够、哪些知识可以暂时跳过。所谓“从零开始”,不是让你把机器学习教科书从头啃到尾,而是用项目倒逼学习,建立一个能支撑你持续迭代的底层框架。下面我就按自己的成长路径,把这个过程完整拆给你看。
1. 为什么说“从零开始”是最容易被低估的路线
1.1 先破除一个幻觉:AI工程师不等于提示词写手
很多人对大模型开发的理解,停留在“写 Prompt 调 ChatGPT”的层面。确实,2023 年初的时候我也这么以为,觉得只要学会了写 Prompt,再套一层 API,就能做出产品。但真正动手后你会发现,Prompt 只是最表层的那一层皮,它背后的问题拆解、数据流设计、结果评测、异常兜底,每一个环节都比写几句指令复杂一个量级。
举一个最简单的例子。你想做一个文档问答机器人,表面上是“把文档扔给大模型,让它回答”,实际上你要处理的是:文档怎么切分、切多长、重叠多少、怎么存、怎么检索、检索结果不够时怎么办、模型答非所问时怎么兜底、回答里的引用怎么标。这一串问题没一个能在 Prompt 里解决,全是工程问题。
所以我对“从零开始”的理解是:把大模型当成一个组件,而不是把大模型当成全部。真正的 AI 工程能力,是你知道这个组件在什么条件下会失灵,然后用工程手段围绕它构建一个稳定的系统。
1.2 从零开始到底要走过哪几个阶段
以我的实际经历来看,这条路线大致可以分成三个阶段。
第一阶段是“能跑通”:会用 API、能把一个简单示例复现出来、能看懂别人的代码。这个阶段大概花了我两到三周,目标是建立信心——原来张张嘴就能让模型干活这件事真的可以落地。
第二阶段是“能做好”:开始理解模型的能力边界,知道什么任务适合大模型、什么任务不适合,开始自己动手写数据清洗脚本、写评测代码、调参数。这个阶段最长,我从第四个月一直持续到现在,它会伴随你的整个职业生涯。
第三阶段是“能上线并能迭代”:你关心的不再只是单次回答质量,而是延迟、成本、稳定性、可维护性。到什么程度算完成?就是你敢把一个系统丢给真实用户,并且知道出了问题去哪里查。
这三个阶段不是割裂的,它们会反复重叠。但有一个共同的底层逻辑:你学的每一个知识点,都应该能回答“它帮我解决了哪个具体问题”。以这个标准去筛选学习内容,你就能从海量的教程和课程里挣脱出来,走一条真正高效的路线。
2. 地基阶段:动手之前必须补齐的四块短板
如果你完全零基础,我强烈建议不要在第一步就去调大模型 API。不是说不能碰,而是说一旦遇到问题,你连排查的方向都没有。我见过太多人卡在“为什么我的 API 调用报错”这种问题上,结果发现连 Python 的异常处理都没看明白。所以先用两到三周把下面四块地基打好,后面会快得多。
2.1 Python工程能力:不是会写脚本就行
这里说的 Python 工程能力,指的是变量作用域、异常处理、装饰器、列表推导式、文件操作、常用标准库这七样东西,而不是去啃什么元类、协程的高级用法。你只需要达到“敢说我能独立写一个两百行的小工具”的程度。
我当时的判断标准很简单:能不能把一个 JSON 文件读进来,做字段过滤、格式转换,再写成新的 JSON。这个动作在后续所有项目里都会反复出现——数据清洗、评测集构建、结果汇总,全是它的变体。如果你五分钟能写完这个脚本且无 Bug,Python 基础就算过关了。
在此基础上,我建议你顺手接触一下 Git 和命令行。因为后续所有项目的代码管理都靠 Git,所有环境安装都靠命令行。这两个技能不需要精通,但git add、git commit、git push、cd、pip install这几个命令要用得闭着眼都能打出来。
2.2 数据动手能力:模型吃进去的是数据,吐出来的也是数据
很多人忽略这一块,但我认为它是区分“教程党”和“工程党”的关键。大模型应用里,你绝大部分时间不是在写模型调用逻辑,而是在处理数据。构造训练数据、清洗用户上传的文档、解析模型输出的 JSON、把不同来源的数据对齐,这些占了我实际开发时间的一半以上。
零基础阶段,你至少要会处理三种格式:JSON、CSV、Markdown。其中 JSON 是重中之重,因为大模型输出结构化内容时几乎都用 JSON。你要熟练到能写出“把 JSON 中某个数组字段拆开,转成一行一条记录的 CSV”这种逻辑,并且处理好嵌套结构。
另外学一点正则表达式,不需要背,知道.*匹配任意字符、[0-9]匹配数字、用括号捕获分组就够起步了。后面你会用它清洗文本、判断格式、提取关键字段,非常频繁。
2.3 基础机器学习直觉:梯度、损失、过拟合
我知道很多人看到“机器学习”四个字就想跑。但说实话,AI 工程岗位需要的不是你能手推梯度公式,而是你有三组概念的直觉:什么是损失函数、什么是过拟合、什么是模型能力边界。
举个例子。你在做 RAG 问答时发现模型总是回答得“太发散”,很可能是检索回的上下文太杂,模型被无关信息带偏了——这在本质上就是某种“过拟合”问题,无关信息占太多,干扰了正确答案。有了这个直觉,你就知道解决方向是优化检索,而不是改 Prompt。
我当时是花了一个周末,把一个经典的手写数字识别示例(用 PyTorch 跑 MNIST)从头看了一遍。不求自己写出来,只看懂“数据进来、模型算、损失下降、参数更新”这个循环是怎么回事。看完之后,你再回去看大模型的原理介绍,很多名词就不那么吓人了。
2.4 评测意识:这是决定你能不能走远的分水岭
这第四块短板是我最想强调的。在 AI 工程里,“感觉效果变好了”是最常见的误判来源。你改了一个 Prompt,测了三条问题,觉得回答顺滑了很多,就以为优化成功了。但真实场景下,你可能只改了 20 条问题里的 3 条,另外 17 条可能反而变差了。
所以从第一天起,就要建立这样的习惯:任何改动之前,先想好怎么测、拿什么测、改完如何对比。哪怕只是手动挑十道题形成一个“最小评测集”,也比拍脑袋改参数强十倍。评测意识不是后期加上的技能,它应该贯穿你接触 AI 工程的全过程。
3. 第一个可用的LLM应用:我用三周走通的实操路线
地基打完之后,就该真正动手了。我选择的第一项目是“个人知识库问答助手”——把一堆 Markdown 笔记做成一个能问能答的对话系统。选择它的原因有三点:需求明确、数据可控、技术栈覆盖面全,文档加载、文本切分、向量检索、Prompt 拼装、结果生成,全都能练到。
3.1 环境与选型:本地跑还是调API
动手第一步是决定模型从哪里来。对零基础起步的人,我强烈建议先调现成的 API,而不是本地部署开源模型。原因是本地部署看起来“高大上”,但你会把大量时间耗在显卡驱动、CUDA 版本、内存爆掉这类环境问题上,而不是真正在学 AI 工程。API 模式可以让你跳过这些负担,把所有精力聚焦在“应用逻辑”本身。
我当时的选择是一条几乎零门槛的路线:用 Python 的虚拟环境(venv 或 conda)建一个独立环境,装好openaiSDK、langchain(虽然现在很多人说它重,但对新手它的抽象帮助很大)、chromadb作为本地向量库。整个环境的安装其实就四条命令:建环境、装包、拿 API Key、跑通第一个 hello world 输出。
这里我想特别提醒:不要把 API Key 写死在代码里。用环境变量保存,或者放在.env文件里,这既是为了安全,也是让你从第一天就养成配置管理的好习惯。
3.2 第一个RAG应用:从文档问答开始
RAG(检索增强生成)是我觉得零基础起步性价比最高的项目范式,它不需要你训练任何模型,却几乎覆盖了 AI 工程里最核心的处理链路。最简单的版本就五步:加载文档、按段落切分、把段落写入向量库、用户提问时检索最相关的段落、把检索结果拼进 Prompt 让模型回答。
这个过程的每一步都有坑。拿段落切分举例,我当时犯的错误是按固定字符数硬切,结果一个完整的段落被拦腰截断,检索到的上下文语义残缺,回答质量惨不忍睹。后来我改成按 Markdown 的标题层级来切,一个二级标题下的内容作为一块,质量一下子提上来了。这个经验让我明白:切分策略没有银弹,它的优劣直接取决于你的文档结构。
再比如向量检索,还剩下的一个问题是“检索到的内容可能有噪声”。用户的问题明明问的是 A,检索模块却同时把相关度尚可的 B 段落也返回了,模型就会把 A、B 混在一起回答。解决方案是在拼 Prompt 前加一层相关性过滤:设定一个相似度阈值,低于阈值的段落直接丢弃,宁可让模型说“不知道”,也不要让它胡说八道。
3.3 Prompt迭代:你改的不是词,是任务的边界
很多人以为 Prompt 工程就是学着把话说漂亮,但真正的 Prompt 迭代是在重新描述“任务边界”。同一个任务,模糊的 Prompt 和清晰的 Prompt,产出的质量能差出一个量级。我自己的核心 Prompt 从第一版到稳定版,一共改了大概十几次,每次改完都会跑一遍评测集,看哪些指标变了。
我的一个经验是:尽量把“任务描述”“输入内容”“输出要求”三段隔开。任务描述要明确角色与目标——你是谁、面对什么材料、要产出什么;输入内容要清楚标注来源;输出要求要具体到格式和长度——用几条 bullet 回答、是否有引用、引用怎么标。这套结构能极大降低模型“自由发挥”的概率。
另一个经验是:尽量把约束写成正面规则。与其说“不要编造事实”,不如说“如果信息不在给定的上下文中,直接回答‘未找到相关信息,请补充资料’”。正面规则比负面禁止稳定得多,模型对“不做什么”的理解远不如“做什么”来得准。
3.4 把碎片代码拧成一个完整服务
跑通一个 Python 脚本是一回事,让用户能通过网页或客户端使用又是另一回事。我推进的方式是分三步:第一步,把核心逻辑写成一个独立的qa_engine.py模块,输入问题、返回答案;第二步,用 FastAPI 包一层 HTTP 接口;第三步,用最简单的 HTML 页面做交互框。
这三步里,第一步最重要。把核心逻辑和 Web 框架分离,你能一直在一个干净的环境里调试业务逻辑,而不是每次都在路由函数里翻来覆去。FastAPI 对新手友好是因为它的代码量极小,一个@app.post("/ask")装饰器加一个函数体就够了,还会自动生成接口文档页面,方便你测试。
我用这套组合做的第一个可访问版本,前后花了大约一周的业余时间。虽然界面简陋到只有一个输入框和输出区,但当我在浏览器里敲出一个问题,几秒后看到模型带着引用来源给出回答的那一刻,整个前三周的学习都在那一个瞬间闭环了。
4. 评测先行:模型选型和效果判断的正确姿势
如果你只打算做一个 Demo,到上一章就可以收工了。但如果你想让系统的效果从“偶尔惊艳”变成“稳定可用”,必须开始建立评测体系。这一部分我花了很大篇幅学习,也走了不少弯路,写下来希望能帮你避雷。
4.1 先建评测集,再谈参数调优
我犯过最多时间的错误,就是没有评测集就开始调 Prompt 和参数。每次改动只凭“感觉差不多”,结果下一次改动又把效果改了回去,完全无法积累。
所谓“最小评测集”,其实就是你挑的二十到五十条有代表性的问题,覆盖正常提问、边界提问(比如问文档里没有的内容)、复杂提问(需要综合多个段落才能回答的)。我给每条问题准备一个参考答案,并注明这个问题的用途,比如“测引用准确性”“测拒答能力”“测上下文容量”。
建好评测集后,对每一次模型参数调整、Prompt 修改、切分策略调整,都要跑一遍评测集,记录通过率。这样你能清楚地看到:这次改动让 35 条里的 31 条达标,比上一版的 29 条好,可以保留;下次让 27 条通过,回滚。有了这套机制,你掌握的技术手段越多,系统就越是越改越稳,改得慌的时候基本在前期就消失了。
4.2 量化指标之外,别忘了“错误聚类”
量化指标告诉你“好不好”,但没告诉你“哪里不好”。所以每次跑完评测集,我会把失败案例集中拿出来做错误聚类——就是人工看这些错误答案,给它们归归类。
我的测评分类通常是这几种:找不到关键信息(检索漏了)、找到但没用上(检索相关度排序有问题)、用了但理解错了(Prompt 指令不清晰)、完全像是在乱说(模型幻觉)、格式不对(输出解析失败)。按这个分类把失败样本贴到一张表里,你就会看到每类问题大概占多少。先处理占比最高的那一类,往往一次改动就能拉升整体通过率五到十个百分点。
当时我的系统里最大一类的错误是“找到但没用上”,后来发现问题出在上下文拼装顺序上:最相关的段落排太靠后,模型被前面的内容带着走。调整检索结果的排序方式后,这类错误几乎消失。
4.3 回归测试:每次改Prompt都要跑的清单
线上系统最怕的不是犯错,而是“改坏了不知道”。AI 应用尤其如此,因为大模型不是确定性的,同一套输入可能生成不同答案。我的应对方法是固定三项检查,把它们做成一个脚本,每次改动后跑一遍。
第一项是核心场景检查:最常用的三到五条典型问题,输出必须达标;第二项是边界拒答检查:喂几个明显超出文档范围的问题,必须正确拒答;第三项是解析稳定性检查:模型输出的 JSON 能否被正确解析,解析失败率不能超过某个阈值。
这套回归脚本实际上就是一个最轻量级的 CI(持续集成)。肝了两次我总结出来的经验是:它不需要完美,甚至不需要自动化,哪怕只是手动跑一遍并记录结果,价值都极大。你唯一需要坚持的,是在“想改”和“敢改”之间始终保留这个检查动作。
5. 从小Demo到能上线:工程化最容易踩的三个坑
当我把 Demo 展示给朋友时,他们都说有意思,但我很清楚:距离一个能被真实用户使用的系统,还差着好几条街。Demo 关心的是“能不能跑”,线上系统关心的是“能不能持续跑”,这中间的工程化鸿沟,是绝大多数人栽跟头的地方。
5.1 延迟与成本:模型快不代表系统快
第一次上线时,我最天真的一件事是:觉得模型返回速度快,系统就一定快。但用户点击“发送”到看到答案,中间实际经历的是:请求到服务器、文档检索、Prompt 拼装、模型生成、结果解析、返回渲染。向量库数据量大之后检索变慢,或者检索没有做索引,都会成为瓶颈。
我当时的解决方法是加两层优化。第一层是检索层加缓存:对相同问题直接返回上次的结果,不再重复查询向量库,也能省模型调用费用;第二层是对模型生成做流式输出——让用户先看到文字逐字出现,而不是干等几秒后一次性出全部结果。这个改动对用户体验的提升,比优化模型参数还明显。
另一个容易被忽视的是成本。大模型按 Token 计费,一个带引用的长答案,一次可能吃掉你几百个输出 Token。上线后流量一大,月底账单会吓你一跳。成本意识要提前建立:限制最大输出长度、对超长文档只检索必要段落、非核心场景用便宜的小模型,这些都是最基础的控成本手段。
5.2 缓存与降级:线上系统不是“尽力而为”
Demo 阶段,模型答不上来时,你会觉得“反正只是演示,无所谓”。线上系统不一样,用户不会因为你模型抽风就体谅你。所以我在上线前补了三个兜底机制。
第一个是超时控制:给每个环节设超时阈值,比如检索超过三秒就跳过直接进生成,模型响应超过三十秒就返回“系统繁忙,请稍后再试”。第二个是固定兜底话术:模型生成结果为空或解析失败时,返回一个友好提示,而不是一个丑陋的报错页。第三个是降级路径:向量库不可用时,直接退化成“只看用户上传的文件名做简单匹配”,或者提示用户稍后再来。
这些机制的本质是同一个思想:系统要能在异常状态下仍给出可接受的响应。模型会失效、数据库会挂、网络会抖动,这些都不是“如果”,而是“什么时候”。把兜底做好,你的系统才算真正从 Demo 迈向了服务。
5.3 可观测性:没有日志检索就不算部署成功
上线第一周,用户反映某个问题“偶尔答得不对”。我当时的反应是:无从下手,因为我根本没记录线上问题的输入和输出。这是可观测性缺失的典型教训。
从那之后我加了三个最基础的观测点:结构化日志(每次请求的输入、检索到的段落 ID、模型返回、耗时、是否命中缓存)、错误追踪(按错误类型统计数量),以及问答回放(能按时间线看用户这次问答的全过程)。不需要上多复杂的链路追踪工具,一个日志文件加一个简单的 SQLite 存储就够了,关键在于你以后能回答“用户这一步到底输入了什么”。
很多小团队连这一步都没有,出了问题只能靠用户截图来定位,这是最低效的工作方式。我宁愿在开发时多花半天加日志,也不想上线后花一个通宵靠猜来排查问题——还真这么干过一次,身兼产品、客服、运维的感觉太差了。
6. 走到今天,我重新理解了“从零开始”这件事
6.1 那些我一开始以为用不上的知识
回看这一年多的经历,有个挺有意思的反差:当初我觉得“用不上的东西”,现在都在关键节点救了我一把。比如正则表达式,我当时只是顺手学的,结果后来写数据清洗脚本时高频用到;比如 Git,我第一次用是在本地仓库瞎折腾,后来协作开发时全靠它协调;再比如基础的 HTTP 知识,我当时以为“调 API 只要会用 SDK 就行”,结果排查线上问题时全靠自己看状态码和响应头。
这让我意识到,“从零开始”不是指把所有知识按顺序学完再动手,而是在动手过程中,发现那些你曾经忽略的知识突然变得有用了。真正学得牢的东西,都是你在项目里踩坑后回头补的知识——它们的价值标准只有一个:是否被你亲手用过。
6.2 给后来者的一份“最小启动清单”
如果有人让我整理一份“从零开始成为 AI 工程师”的最小启动清单,我会不加犹豫地给出四样东西:一条跑通的核心链路(调用模型 API 并可靠解析输出);一个你自己定义的评测集(至少十条覆盖正常与边界问题的题目);一个能记录输入输出和耗时的日志模块;一个兜底响应分支(所有异常场景至少有一条可接受的返回)。你把这四样东西拼在一起,就是一个最小的“AI 工程能力容器”,接下来的所有项目都往这个容器里加东西。
我自己的体会是,这条路的门槛不在于数学,也不在于天赋,而在于你能不能坚持在“会跑”和“能稳定跑”之间反复打磨。第一次跑通只要几天,难的是让它在第一百次运行时依然稳定、第一百个用户使用时依然可用。但这恰恰是 AI 工程最有趣的地方——它把看似玄学的“模型效果”变成了可测量、可迭代、可复盘的工程对象。如果你正在这个路口犹豫,我的建议是:不用等我这样的长篇复盘了,直接打开终端,让你的第一行代码先跑起来。后面所有的问题,都会在“跑起来”之后一个个浮出水面,而解决它们的过程,就是你的“从零开始”。