很多朋友看到“ai-engineering-from-scratch”这个标题,第一反应是“又要堆一堆数学公式”或者“又是调库调参的教程”。其实我当初开这个项目的时候,想法特别朴素:能不能不依赖任何商业闭源服务,只用开源工具,从一台干净的电脑开始,把一个真正能跑的AI应用给搭出来。我不是做算法研究的,我是个做后端开发的,我更关心的是模型怎么部署、数据怎么流转、接口怎么设计、系统怎么稳定跑起来。这套东西,圈里人叫“AI工程”,但说实话,很少有人能讲清楚它和“AI研究”到底差在哪。这篇文章就是把我从零开始折腾这个项目的过程、踩过的坑、以及最后沉淀下来的一套思路,完完整整分享出来。
先说结论:AI Engineering的核心不是训练模型,而是用工程手段把模型变成产品里一个稳定、可控、可维护的组件。从零开始做AI工程,重点不在啃深度学习理论,而在建立一套围绕模型的工程链路:数据怎么准备、模型怎么选、怎么推理、怎么部署、怎么监控、怎么迭代。这个项目做完之后,我最深的感受是:AI工程的门槛不在“AI”两个字,而在“工程”两个字。下面我会按照我的实际实践路径,把每一步怎么走、为什么这么走、以及过程中遇到的典型问题,都讲清楚。
1. AI工程与AI研究的核心区别:先搞清楚你在做哪件事
1.1 两者的目标完全不同
我在项目初期最大的困惑就是:到底学多少算法才算够?后来一个做算法岗的朋友点醒了我——AI研究追求的是“模型能力的上限”,AI工程追求的是“模型能力的稳定释放”。这完全是两个维度。研究者在意的是在某个评测集上把准确率从90%提到91%,哪怕为此要调三天参数;工程师在意的是模型在线上跑一个月不出故障,接口响应稳定在几百毫秒以内,成本可控,出问题时能快速定位。
认知一旦切换,学习路径就清晰了。我不需要去推导Transformer里的注意力公式是怎么来的,但我需要知道它的计算复杂度对推理延迟意味着什么;我不需要从零训练一个大模型,但我需要清楚不同开源模型的参数量、显存占用和推理速度差异;我不需要理解反向传播的每一个数学细节,但我必须知道推理时的KV Cache会占多少内存。换句话说,AI工程要求的是“够用的算法理解”加上“完整的工程能力”,而不是“深厚的学术功底”。
1.2 一个完整AI应用系统的构成要素
要把AI能力嵌入到一个真实产品里,远不止“调用一个模型接口”那么简单。我在项目里梳理了一个最小可用系统的构成清单,这里直接列出来,你可以对照着检查自己的项目缺了什么:
- 模型层:开源模型(如Qwen、Llama)或商业API,负责核心的推理计算。
- 数据层:知识的来源,可能是结构化数据库、非结构化文档,也可能是实时抓取的网页内容。
- 向量化与检索层:把数据切成块、转成向量,存进向量数据库,在需要时做相似度检索。
- 推理服务层:模型部署成HTTP接口,内含请求排队、流式输出、超时处理、并发控制。
- 业务逻辑层:把检索结果、模型输出和业务规则粘合起来,比如判断什么时候该调用模型、什么时候走预设答案。
- 可观测层:日志、指标、链路追踪,知道系统在干什么,出了问题能找到原因。
如果只把模型API接入到一个Demo里,那不叫AI工程,那叫API调用。工程化的标志是:每一层都有明确的设计,每一层都能独立测试和替换,每一层出问题都有预案。这是我做完这个项目后最强烈的一个体会。
2. 从零起步的技术选型:为什么我选了这条开源路线
2.1 硬件条件决定了你的路线
做AI工程,第一个现实问题就是“你手上有什么算力”。我自己的机器是一张消费级的GPU,显存比较有限。这个条件直接帮我做了决策:别碰13B以上的大模型,聚焦在1.5B到7B这个区间。很多人一上来就想跑最大的模型,结果连加载都加载不进去,热情瞬间被浇灭。
我建议你先做一次显存估算。以7B模型为例,如果用FP16精度加载,光模型权重就需要大约14GB显存。推理过程中还有KV Cache和激活值,实际占用会更高。如果把模型量化到INT4,显存需求能降到4GB左右。这个计算过程很重要——它决定了你该选多大的模型、要不要量化、能不能同时跑多个实例。我当时的选择是:用4~7B规模、量化到INT4或INT8的模型跑主力场景,既保证了效果,又留出了显存余量做其他事情。
2.2 推理框架选型:不能只盯着模型文件
模型本身只是权重文件,真正让它跑起来的是推理框架。我对比了几个主流方案,这里直接给结论。如果说你追求极致的推理性能和灵活的部署方式,TGI和vLLM是首选,它们实现了continuous batching,能把GPU利用率拉得很高。但这两个框架对显存和依赖环境要求偏高,起步稍重。如果你希望快速上手、生态丰富,可以选Ollama,一条命令就能把模型跑起来,内置了量化支持和OpenAI兼容接口,特别适合开发和测试。如果你要做的是轻量级嵌入式或者需要极致定制,那llama.cpp系列会更合适。
我的建议是:不要在一开始就纠结“哪个框架最强”,而是选一个“今天就能跑起来、后面不阻碍你换”的。我最后选了Ollama做起步,因为它的OpenAI兼容接口让我可以先用标准方式把应用逻辑跑通,后面就算换框架,代码改动也几乎没有。这种“接口标准先行”的思路,帮我省了大量重构时间。
2.3 向量数据库与Embedding模型的选择
对于要做知识库问答的应用,向量检索是核心链路的一环。Embedding模型负责把文本变成向量,向量数据库负责存储和检索。开源方案里,嵌入模型推荐bge系列或gte系列,它们在中文场景下表现不错;向量数据库我选了支持本地嵌入的Milvus Lite或者Chroma——没错,这俩都是开源方案,完全本地部署。
选型逻辑是这样的:嵌入模型决定了“检索的召回效果”,也就是你能不能找到该找的东西;向量数据库决定了“检索的速度和规模”。一开始完全可以用Chroma这种轻量方案把链路跑通,等数据量涨到百万级再迁移到专门的向量数据库。工程上有个原则叫“延迟决策”——不要提前为不存在的规模做架构设计,我在这上面吃过亏,后面细说。
3. 实操过程:从零搭建一个“最小可用”的AI问答系统
3.1 项目目标与整体架构规划
我的项目目标是做一个“本地知识库问答系统”:给定一批技术文档,系统能根据用户提问,从文档中检索相关内容,交给大模型组织成答案。整个系统完全跑在本地,不依赖任何外部商业API。
架构拆解下来就五块:文档加载与切分、向量化入库、检索、推理、包装成HTTP接口。这个结构非常经典,很多人叫它RAG。我刻意没有一开始就上Agent、工具调用这些高级特性,因为我知道:先跑通主链路,再去加花活,这个顺序不能乱。
3.2 文档处理与向量化:最先出现的坑
第一步是准备知识库。我找了一批技术文档,格式有Markdown、也有PDF。文档处理的第一道工序是“清洗”,这一段我就踩坑了。PDF转出来的文本经常有乱码、多余的换行和页眉页脚,如果不处理直接切块,检索质量会大打折扣。
切块这一步,最考验经验。块太大,检索出来的内容不精准;块太小,上下文信息不完整。我的做法是:优先保证每个块是一个语义完整的段落,而不是机械地按固定字数切。比如按“标题+段落”的结构切分,每个块控制在200到500字之间,相邻块保留一定重叠。这样在检索的时候,召回的内容信息密度最高。
向量化的过程反而是最顺利的——选定一个嵌入模型,把文本块批量转成向量,存入向量数据库,就完成了。这一步的核心参数是向量维度,它决定了后续检索的内存占用和速度。这里有个工程心得:嵌入模型不是越大越好,选一个中等规模、在目标语言上表现好的就行,因为检索效果更多取决于文档切分质量。
3.3 检索链路与Prompt设计:决定回答质量的“隐形杀手”
很多人在RAG系统里用力调Prompt,却忽略了检索质量。其实Prompt只决定“模型的嘴巴”,检索决定“模型的食粮”。如果检索回来的内容本身就文不对题,你再怎么调Prompt也白搭。
我做了三种检索策略的对比,效果差异很明显:第一种是纯向量检索,用文本相似度找TopK,快但容易漏掉关键词精确匹配;第二种是向量检索加关键词过滤,先按业务规则筛掉不相关文档,再做相似度排序,效果稳步提升;第三种是重排序,用精排模型对候选结果重新打分,效果最好,但会增加几十毫秒到上百毫秒的延迟。
在实际项目中,我先用了向量+关键词过滤的组合,效果够用,延迟低。重排序我留在了后面的迭代计划里,等收集到足够的badcase再上。这个决策背后的思路是:不要让系统为了“更加精确”而牺牲“最简单可靠”,尤其在初期。
Prompt设计方面,我总结了一个三明治结构:系统指令明确角色和约束,用户问题放在中间,最后注入检索到的上下文。这个结构比单句“请回答以下问题”稳定得多。另一个原则是:告诉模型“如果检索内容不足以回答问题,就如实说不知道”,这能明显减少一本正经的胡说八道。
3.4 服务封装与前后端联调:从脚本到产品
模型跑通之后,最重要的一步是把它封装成服务。我没有自己撸HTTP框架,而是直接使用了推理框架自带的类OpenAI接口,然后写一个薄薄的调度层。这个调度层负责三件事:接收请求、调用检索链路、把结果返回给客户端。
流式输出是个值得注意的细节。大模型生成答案需要时间,如果做成一次性返回,用户会等得很焦躁。我花了一些时间把流式输出做通了——先把数据源切换成服务端流式返回,前端再逐步渲染。这个体验上的提升非常明显。但要提醒的是:流式返回会把错误处理变复杂,因为你不能确定“已经发给用户的那些内容”是否应该撤回。所以我额外的做法是:对前端只提示“生成中请稍候”,一旦出现不可恢复的错误就中断输出并给出提示。
前后端联调阶段,我遇到了一个典型问题:本地模型服务器的并发能力非常有限,前端一刷新页面,瞬间发起多个请求,直接把模型打挂。后来我加了两个措施:HTTP连接复用和请求排队。模型服务只允许几个并发请求,超出部分排队等待,效果立竿见影。如果你是“从零开始”做AI工程,这几条建议都建议直接抄走。
4. 完整部署实战:模型量化、接口对接与性能调优
4.1 模型量化不是玄学:先搞懂你的显存瓶颈
部署到一台只有一张GPU的服务器上时,量化几乎是必选项。我在项目里把7B模型从FP16压到了INT4,显存占用降了接近一半,推理速度因为访存减少反而有一定提升。这个结果让很多新手意外,以为量化一定会降低速度,其实在大模型推理里,瓶颈往往在显存带宽而不在计算,INT4让模型体积变小,反倒跑得更快。
但量化不是魔法,它对精度有影响。我的建议是:先用INT8做过渡,如果显存还是吃紧,再上INT4。如果你的业务场景对数值敏感度极高,量化前后一定要做评测对比,不能光看“跑起来没报错”。我自己的经验是,对于问答、摘要、聊天这类生成任务,INT4的损失基本感知不到;但如果做数学运算或严谨的多步推理,INT4可能让答案质量明显下降。
4.2 推理性能调优:从“能用”到“好用”
部署上线后,我花了不少时间调推理性能。第一个大发现是:并发吞吐跟“首字延迟”是两回事。有的框架首字出来快,但并发一高就明显变慢;有的框架首字稍慢,但并发很稳。这取决于是否实现了动态批处理。选框架的时候,别只看单次请求的延迟,要压测并发场景下的综合表现。
第二个经验是关于文本长度限制的。大模型有输入长度上限,一旦超出就报错。工程上要在接口层做长度校验和截断策略,不能让用户的请求直接打到模型层。我踩过一次坑:一个超长文档被检索命中,直接拼进Prompt,结果请求报错,用户看到的是“服务器内部错误”。后来我加了一个“按token数预估文本长度,超出则取关键段落”的逻辑,问题立刻消失。
第三个方法是建立缓存层。我用了语义缓存:相同的提问,直接返回上次的结果。这个策略对重复性较高的业务场景特别有效,命中率上来后,大幅降低了模型调用量。这里有个小技巧——在做向量检索时,先用高阈值让系统判断“现在这个问题和以前某个问题像不像”,如果相似度很高,就直接命中缓存,不用再走模型。这个机制在真实场景里能省下不少真金白银。
4.3 模型接口的标准化:给自己留一条后路
这是我项目里做得最值得的一个决定:从一开始,我就让我自己的业务代码只认OpenAI兼容的API格式,而不是直接调用具体某个推理框架的私有接口。这个抽象层带来的直接好处是:当我从Ollama切换到vLLM、或者从本地模型切换到某个商业模型服务时,业务代码一行都不用改。
很多教程不会强调这一点,但我建议你专门为“模型接入”写一个Provider层,把模型调用、重试逻辑、超时策略、错误映射都封装起来。接口标准化不单是代码层面的优雅,更是“工程化”和“写脚本”的分水岭。
4.4 前端集成与用户体验细节
前端集成的重点就四个字:管理预期。大模型的生成速度再快也有延迟,所以前端要处理好加载态、错误态和流式展示。我的前端代码里专门为“生成中”设计了一套过渡UI:显示“正在检索资料”、“正在生成回答”等步骤,用户看到系统在干活,就不会觉得卡死了。
还有一个细节是“停止生成”按钮。流式输出时,用户可能觉得答案已经够了,想中断生成,这个操作在工程实现上就是断开底层的响应流并取消模型的后台计算。没做过的人可能觉得这很难,其实一个中断标记加一次底层取消调用就够了。做过交互设计的朋友会知道,这个小功能对用户耐心的影响是很大的,强烈推荐加上。
5. 工程化路上的硬仗:可观测性、评估与迭代闭环
5.1 日志、指标、链路追踪:上线第一天就要有的“三件套”
项目上线前,我把监控体系补上了。模型服务端要记录:请求延迟、Token消耗、错误码、输入输出长度。业务服务端要记录:检索命中文档、检索耗时、最终回答的完整内容。这两类日志混在一起会很难排查问题,所以我给每条请求生成了唯一的请求ID,贯穿检索、推理、返回全链路。任何一条回答出问题,我都能在日志里翻出“用户问了什么、检索到了什么、模型说了什么、耗时多少”。
可观测性最直接的效果是:用户说“回答不对”的时候,你能快速判断是检索没召回正确内容,还是模型没用好检索内容。这个二分法是排查RAG问题的基本框架——“召回问题”和“生成问题”的解法完全不同,前者要调切分和检索策略,后者要调Prompt或换模型。
5.2 离线评估和在线反馈:用数据而不是感觉来迭代
系统上线后,我最怕的就是靠“感觉”去改系统。所以我搭了一套简单的离线评估集:找了大概200个典型问题,每个问题写了标准答案和相关的文档ID。每次改动,比如调整切分大小、换嵌入模型、改Prompt,我都在这个评估集上跑一遍,计算“检索召回率”和“回答正确率”。
这个流程的价值怎么强调都不为过——没有评估,你根本不知道一个改动是在变好还是变坏。有几次我改了Prompt后,感觉回答更流畅了,但评估分数反而下降。这说明“感觉好”和“质量高”不总是一回事。许多项目最后死在“优化无数却退步不知”,本质就是没有评估体系。
5.3 从Demo到产品的最后一步:理解用户并不关心模型
上线运行一段时间后,我让几个非技术的朋友试用。反馈让我很清醒:他们根本不关心你用的是什么模型、有没有用RAG、向量库是哪个。他们只关心三点:回答问题准不准、速度快不快、别动不动报错。
这意味着工程优先级非常明确:稳定性大于效果优化,速度体验大于花哨功能。一个真实用户不会因为你用了最新的模型就原谅你三秒的加载卡顿。所以在后续迭代里,我优先处理了超时重试、接口容错、并发控制这些“不性感”的部分,然后才是效果优化。这条经验比任何一个技术选型都重要。
6. 常见问题与排查技巧实录:从一次次翻车中学到的
6.1 冷启动阶段最容易踩的坑
第一个坑是环境依赖冲突。Python的依赖管理在AI项目里会非常痛苦——PyTorch要特定版本的CUDA,向量库要特定版本的numpy,框架之间互相打架。后来我全部改用容器方案,把环境固定在镜像里,问题迎刃而解。这也符合工程化的原则:环境要可复现,别在你自己的电脑上能跑、换个机器就废了。
第二个坑是模型下载慢。开源模型动辄几个G,下载失败是家常便饭。我的做法是:先用命令行工具手动下载好模型文件,放到本地模型目录,然后再让推理框架加载本地路径。这样即使下载中断,也能断点续传,比框架自带的下载机制更可控。
6.2 运行时常见问题速查表
整理一份我遇到的典型问题和排查方法,基本覆盖了从零到上线的全过程:
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 模型加载时显存不足 | 模型精度过高或文件缺失 | 换量化版本,或加虚拟内存,但速度会受影响 |
| 接口响应很慢但CPU不高 | 模型推理是GPU任务,看GPU利用率 | 检查是不是没有启用GPU推理,跑在CPU上了 |
| 回答内容明显不对 | 检索召回的内容不相关 | 看日志里的检索结果,先查召回再查Prompt |
| 偶发超时 | 推理队列堆积 | 加并发控制,超时重试,客户端做降级提示 |
| 向量检索结果不理想 | 文档切分不合理 | 调整块大小和重叠度,检查嵌入模型是否匹配语言 |
| 多用户同时用就卡死 | 并发处理能力不足 | 启用动态批处理,或者加服务实例做负载均衡 |
| 输入内容过长报错 | 超出模型上下文 | 在接口层做长度截断,或者分块多次调用 |
6.3 一个花了很长时间才发现的“隐形罪魁祸首”
项目中有一个问题折磨了我很久:模型偶尔会出现答非所问的情况。日志显示检索到的文档是正确的,模型却还是胡言乱语。后来我发现——问题出在检索结果拼接顺序上。我把多个文档块按相似度分数从高到低拼接进Prompt,结果模型误以为排在最前面的是最重要的指令,开始“执行”文档里的内容,而不是“回答”用户的问题。
解决方式很简单:在Prompt的检索上下文开头加一句明确说明,比如“以下资料仅供参考,请基于它们回答用户问题”,同时在拼接顺序上让用户问题始终保持在最前面。这个细节说来简单,查起来却要花很久。这类问题,通常只有实际做过并吃过亏的人才会知道,文档里根本不会写。
7. 从项目回顾看AI工程学习的成长路径与个人感受
7.1 回头看:“从零开始”最难的其实是确定“到哪算会”
做这个项目前,我总觉得“从零开始做AI”是一件特别大的事,好像得先读完几本书、刷完几门课才能动手。真正做过一遍之后,我发现学习路径完全可以反过来:先定一个明确的目标,比如“做一个能回答我文档问题的机器人”,然后倒推需要的技术栈和工具链,遇到什么学什么。这个模式的好处是,每一个知识点都立刻有使用场景,学完就能用,成就感是持续供给的。
学习模式上一个很有帮助的做法是:不跟教程走,而是“对着官方文档去搭”。教程的问题在于它把步骤都替你踩平了,遇到问题你不知道为什么。我自己搭的时候,故意不全程跟着别人的教程来,而是理解官方文档里各参数的含义,自己拼。摔几次跟头之后,那些模块之间的关系就清楚了——这比看几十遍教程都有用。
7.2 不同基础的读者,如何规划自己的路径
如果你是完全没接触过AI工程的新手,我建议先别碰训练、微调这些重活。先把“加载一个开源模型 → 用标准接口调用 → 做个简单的问答脚本”这条链路跑通,你就算入门了。过程中你只需要一点点Python基础和最基本的机器学习概念就够了。
如果你已经是后端工程师或者熟悉常规软件开发,你的优势其实非常大。你对API设计、并发控制、日志监控、系统架构的理解,在AI工程里全部用得上。你缺的只是“和模型打交道”的这一小段经验,补起来并不难。这类朋友我建议直接把重点放在RAG链路的搭建和工程化打磨上,你会发现自己能比“算法背景”的人更快做出一套可用的系统。
如果你是算法出身,对模型本身很熟,那你的短板通常在软件工程规范上。环境隔离、CICD、可观测性、代码评审,这些看起来“不酷”的东西,恰恰是AI产品能否规模化的关键。工程化能力的补齐,会让你的研究成果更快被真正用起来。
7.3 最后分享一个建议:“别把模型当黑箱,也别被模型绑架”
最后说点个人的体会。做完这个项目,我在笔记本里记了一句话:“AI工程是搭一个容器,模型是里面的水,你要关心的不只是水干不干净,还有容器漏不漏、够不够装、好不好换水。”这个比喻帮我搞定很多决策:当模型效果不够好时,我检查是不是容器(检索链路、Prompt结构、数据处理)的问题;当系统不稳定时,我优先检查工程链路而非模型能力;当想升级模型能力时,我却可以快速插拔换上更新更强的模型,其他模块完全不受影响。容器越稳定,换水就越安全。
从零开始做AI工程,没有什么神秘的火箭科学,无非是:定一个目标、拆一条链路、选一套工具、搭一个闭环、加一套监控。做完这一步,你会发现自己已经拥有了继续深入的基础,而下一步的路,自然就清晰了。