☰
从零手搓AI工程核心链路:分块、检索、推理与评估实战
2026/9/30 12:20:17 网站建设 项目流程

1. 从零搭建AI工程能力:为什么“手搓一遍”比调包更值钱

这两年AI应用开发的门槛肉眼可见地降低了。一个刚入行的开发者,借助现成的框架和API,可能一个下午就能跑通一个对话机器人或者一个RAG问答系统。但如果你真的在团队里带过人、做过线上项目,就会发现一个很尴尬的现象:很多人能跑通Demo,却说不清楚一次推理请求背后到底发生了什么,模型加载慢在哪里、显存为什么爆了、token是怎么被切分的、向量检索的召回率为什么上不去,一问三不知。

“ai-engineering-from-scratch”这个标题,本质上说的就是一件事:把AI工程里那些被框架封装掉的环节,自己动手实现一遍。它不是让你去从头训练一个大模型,那既不现实也没必要,而是让你把推理服务、数据处理、检索增强、评估监控这些工程链路的核心模块,用最朴素的方式亲手搭一遍。做完之后你对整个系统的掌控力,和只会调包的人完全不在一个层次。

这篇文章适合三类人:一是刚转行做AI应用、只会调API想补底层认知的开发者;二是有后端或数据工程背景、想切入AI方向的工程师;三是带团队的技术负责人,想搞清楚AI工程到底有哪些坑、该怎么给团队定技术规范。我会把整条链路的搭建思路、关键取舍、实测踩过的坑都摊开讲,尽量让你看完就能自己动手复现。

需要先说明一点:下面涉及的具体参数、工具选型,都是基于我在实际项目中的常见实践给出的合理方案,不是唯一答案。你要根据自己的硬件条件、数据规模、团队技术栈去调整,重点是理解每一步“为什么这么做”。

2. 动手之前先想清楚:AI工程到底在工程什么

2.1 把“模型”和“工程”分开看

很多人一上来就纠结模型选型,觉得模型选对了项目就成功了一半。实际做下来你会发现,在一个真实的AI应用里,模型只是其中一个组件,而且往往是相对稳定的那个。真正消耗你80%精力的,是模型之外的那一圈东西:数据怎么进来、怎么切、怎么存、怎么检索、怎么拼装成prompt、怎么控制并发、怎么监控质量、怎么迭代。

我习惯把AI工程拆成四层来看。最底层是基础设施层,包括算力、显存管理、模型加载与推理引擎;往上是数据层,包括文档解析、分块、向量化、存储与检索;再往上是编排层,负责把检索结果、对话历史、系统指令组装成最终输入,并管理多轮状态;最上面是应用与评估层,面向具体业务场景,同时负责质量监控和效果评估。从零搭建,就是把这四层里最核心的模块各实现一个最小可用版本。

这样拆的好处是,你不会被某个框架的抽象概念绕晕。任何一个AI框架,你都能把它对应到这四层里,看它到底帮你做了什么、隐藏了什么。当你遇到问题时,也能快速定位是哪一层出了毛病。

2.2 最小可用系统该包含哪些模块

如果你时间有限,我建议优先实现这四个模块,它们覆盖了AI工程最核心的能力:

  • 文本分块器:把长文档切成适合模型处理的片段,这是RAG的地基,切得好不好直接决定检索质量。
  • 向量化与检索:把文本转成向量存起来,并实现相似度检索,理解embedding和索引的基本原理。
  • 推理服务封装:把模型加载、请求处理、并发控制、超时重试封装成一个稳定的服务。
  • 评估脚本:用一批标注好的问答对,量化你的系统到底好不好,而不是凭感觉。

这四个模块做完,你就有了一个能跑、能测、能迭代的完整闭环。后面再往上加缓存、加多路召回、加重排序,都是在坚实的地基上做增量。

2.3 一个容易被忽略的前提:先定义“好”的标准

我在早期项目里犯过一个典型错误:花了两周把系统搭起来,跑起来感觉“还行”,但老板问“准确率多少”,我答不上来。因为没有评估标准,你根本不知道系统是在进步还是在退步。

所以在动手写代码之前,先花半天时间做一件事:准备一个评估集。哪怕只有50条数据,每条包含一个问题和一个标准答案(或者标准答案的关键要点)。这个评估集会贯穿你整个开发过程,每次改动后跑一遍,看指标是涨是跌。没有它,你的所有优化都是盲人摸象。这是我从零搭建AI系统时,认为最重要、也最容易被跳过的一步。

3. 文本分块:RAG效果的天花板往往在这里就被决定了

3.1 为什么固定长度分块是个陷阱

大部分教程教你分块,就是按固定字符数切,比如每500字一块,重叠50字。这个方法实现简单,但在真实文档上效果很差。原因很简单:文档是有语义结构的,一个完整的论述可能横跨800字,你从中间切断,前半块讲了一半的论点,后半块接着讲结论,两块单独看都不完整,检索时匹配到的都是残缺信息。

我实测过一个技术文档库,固定长度分块和按语义分块,在同一个评估集上的召回准确率差了将近20个百分点。这个差距不是靠换更好的embedding模型能补回来的,因为信息在切分阶段就已经被破坏了。

正确的思路是按语义边界切分。最基础的做法是按段落切,段落本身就是作者划分的语义单元。如果段落太长,再在段落内部按句子切。句子边界识别可以用简单的标点规则,也可以用轻量的分句工具。核心原则是:尽量保证每一块是一个语义完整的单元,而不是机械地凑字数。

3.2 分块大小的权衡:没有标准答案,只有场景答案

分块大小到底设多少,是问得最多的问题。我的经验是,它取决于你的检索粒度和模型上下文窗口两个因素。

块太小,比如100字,检索时匹配很精准,但单块信息量不足,模型拿到后可能答不完整。块太大,比如2000字,信息量够了,但检索时噪声变多,而且一块里可能包含多个主题,相似度计算会被稀释。我一般会在300到800字之间做实验,用评估集跑一遍,看哪个区间的召回和答案质量最好。

还有一个技巧是分层分块。把文档同时切成大块和小块,小块用于精准检索,检索到之后把对应的大块(或者大块加上相邻块)喂给模型。这样兼顾了检索精度和上下文完整性。这个思路在工程上实现起来不复杂,但效果提升很明显。

3.3 元数据:分块时顺手做的事,后面能省大力气

分块的时候,千万别只存文本内容。至少要把这些元数据一起存下来:来源文档ID、块在文档中的位置序号、所属章节标题、块的字符数。这些信息在后续检索、去重、展示引用来源时都会用到。

我踩过一个坑:早期分块只存了文本,后来要做“引用溯源”功能,需要知道每个答案来自哪篇文档的哪一段,结果发现根本追溯不了,只能把整个库重新处理一遍。所以分块阶段多存几个字段,成本极低,收益极高。

另外,如果文档有标题层级结构,把章节标题拼接到块内容前面一起做向量化,能显著提升检索效果。因为标题本身就是对内容的强概括,相当于给每个块加了一个语义标签。

4. 向量化与检索:把“找相似”这件事做扎实

4.1 Embedding模型选型:别只看排行榜

选embedding模型,很多人直接看公开榜单排名。榜单有参考价值,但你的场景和榜单的评测场景可能完全不同。榜单大多测的是通用语义相似度,而你的业务文档可能有大量专业术语、缩写、内部黑话。

我的做法是:选两三个候选模型,用你自己的评估集各跑一遍检索,看召回率。候选模型里,至少要有一个是支持中文或多语言的,因为很多英文榜单冠军在中文上表现会打折。另外要考虑模型的维度和推理成本,维度越高检索越慢、存储越大,如果效果差距不大,优先选维度低的。

还有一个实际因素:模型能不能本地部署。如果你的数据敏感、不能出内网,那就只能选能本地跑的模型。这个约束会直接砍掉一批候选,所以要在选型早期就确认清楚。

4.2 相似度计算:余弦相似度不是唯一选择

向量检索最常用的是余弦相似度,它衡量的是方向上的接近程度,对向量长度不敏感。这在大多数场景下是合理的,因为embedding模型通常会把语义相近的文本映射到相近的方向上。

但有些场景下,欧氏距离或者点积可能更合适。点积在向量已归一化时等价于余弦相似度,计算更快。如果你的embedding模型输出已经归一化,直接用点积就行,省一次计算。我实测下来,在归一化向量上,点积和余弦的结果完全一致,但点积的矩阵运算更快,尤其在大规模检索时差距明显。

实现检索时,最朴素的做法是暴力遍历所有向量算相似度。数据量小的时候(比如几千条)完全够用,而且结果精确。数据量上万之后,就要考虑近似最近邻索引了。但我的建议是:先用暴力检索跑通全流程,确认效果达标后,再考虑换索引优化速度。过早引入复杂索引,调试成本高,而且可能引入精度损失。

4.3 检索质量差,先别怪模型

检索效果不好,很多人第一反应是换更好的embedding模型。但根据我的经验,问题往往出在更前面:分块没切好、查询和文档的表述方式差异太大、或者没有做查询改写。

一个立竿见影的技巧是查询扩展。用户的问题往往很短,比如“怎么配置超时”,而文档里写的是“超时参数的设置方法”。直接拿短查询去检索,可能匹配不上。可以在检索前,用一个小模型或者规则,把查询扩展成几个同义表述,分别检索后合并结果。这个改动不大,但召回率提升很明显。

另一个技巧是混合检索:向量检索负责语义匹配,关键词检索(比如BM25)负责精确匹配。两者结果加权融合。对于包含专有名词、型号、代码的查询,关键词检索能补上向量检索的短板。我在实际项目里基本都会上混合检索,纯向量检索在专业领域文档上经常漏召。

5. 推理服务封装:让模型稳定跑起来比调通难得多

5.1 模型加载:显存、精度与启动速度的三角

把模型加载起来跑通一次推理,和把它封装成一个能扛住并发、稳定运行的服务,中间隔着一整个工程。第一个要面对的就是显存问题。

模型加载占用的显存,主要取决于参数量和精度。以常见的7B模型为例,FP16精度下大约需要14GB显存,INT8量化后降到7GB左右,INT4量化后只要4GB上下。如果你的显卡显存有限,量化是必选项。但量化会带来精度损失,需要评估损失是否可接受。

加载策略上,我建议服务启动时一次性加载,常驻显存,而不是每次请求都加载。每次加载模型动辄几十秒,请求响应时间根本没法看。常驻显存虽然占资源,但换来了稳定的低延迟。如果显存实在紧张,可以考虑多模型共享或者按需加载加缓存,但复杂度会上升不少。

5.2 并发控制:别让请求把服务打垮

模型推理是计算密集型任务,同时处理太多请求会导致显存溢出或者响应时间飙升。必须做并发控制。

最直接的方式是限制同时处理的请求数,用一个信号量或者队列来控制。超出的请求排队等待,而不是直接拒绝。队列长度也要设上限,超过上限就快速失败,返回“服务繁忙”,避免请求无限堆积拖垮整个服务。

另一个关键是批处理。如果多个请求同时到达,可以把它们拼成一个batch一起推理,能显著提升吞吐量。但批处理会增加单个请求的延迟,因为要等凑批。所以要在吞吐和延迟之间找平衡点,通常设一个很小的等待窗口(比如几十毫秒),窗口内到达的请求合并处理。

超时和重试也要设计好。推理请求设一个合理的超时时间,超时后释放资源。对于可重试的错误(比如临时资源不足),做有限次数的重试,但要注意重试不能加剧拥塞,最好带退避策略。

5.3 流式输出:体验提升的关键细节

对话类应用如果等模型全部生成完再返回,用户要盯着屏幕等好几秒,体验很差。流式输出让token一个个吐出来,用户马上能看到反馈,感知延迟大幅降低。

实现流式输出,需要在推理引擎层面支持逐token返回,然后在服务层用SSE或者WebSocket推给前端。这里有个坑:流式输出时,如果中途出错,已经吐出去的内容没法收回,所以要在开始流式输出前做好参数校验和资源检查,尽量把错误挡在前面。

还有一个细节是首token延迟。用户感知的响应速度,主要取决于第一个token多久出来。优化首token延迟,可以从prompt长度、模型预热、KV缓存复用几个方向入手。prompt越短,首token越快,所以检索回来的上下文要精简,别一股脑全塞进去。

6. 评估与迭代:没有度量就没有优化

6.1 评估集怎么建才靠谱

评估集的质量直接决定你优化的方向对不对。我的建议是,评估集要覆盖三类问题:事实型(答案在文档里有明确出处)、推理型(需要综合多处信息)、边界型(文档里没有答案,系统应该拒答)。

每类问题都要有,比例根据你的业务场景调整。如果业务里大部分是事实型查询,那事实型占比就高一些。边界型问题特别重要,因为很多系统在遇到不知道的问题时会胡编,评估集里必须有这类样本,才能测出系统的“诚实度”。

标注答案时,不要只写一个标准答案,最好把关键要点列出来。因为模型生成的答案表述可能和标准答案不同,但要点覆盖了就算对。评估时可以用要点召回率来衡量,比精确匹配更合理。

6.2 自动化评估:用模型评模型

人工评估准确但慢,不适合快速迭代。可以用一个能力较强的模型来做自动评估,给它问题、标准要点、系统答案,让它判断答案覆盖了哪些要点、有没有编造。

用模型评估要注意几点:评估用的模型能力要明显强于被评估的系统,否则评不准;评估的prompt要写清楚评分标准,最好给几个示例;评估结果要做抽样人工复核,确认自动评估和人工判断的一致性。我一般会抽10%的样本人工核对,如果一致性低于90%,就要调整评估prompt。

除了答案质量,还要监控检索命中率(正确文档有没有被检索到)和拒答准确率(该拒答的有没有拒答)。这两个指标能帮你定位问题出在检索层还是生成层。

6.3 迭代的优先级:先修召回,再调生成

系统效果不好时,优化顺序很关键。我的经验是:先确保检索能召回正确文档,再优化生成质量。如果正确文档根本没被检索到,生成模型再强也答不出来,这时候调prompt是白费力气。

判断方法很简单:看评估集里答错的样本,正确文档是否在检索结果里。如果不在,就是召回问题,去优化分块、embedding、查询扩展、混合检索。如果在但答案还是错,才是生成问题,去优化prompt、上下文组织、模型选型。

这个排查顺序能帮你避免在错误的方向上浪费时间。我见过太多团队一上来就疯狂调prompt,结果发现根因是分块把关键信息切碎了。

7. 那些文档里不会写的实操心得

7.1 关于工具选型的一点个人偏见

从零搭建不等于什么都自己写。向量存储、推理引擎这些轮子,该用现成的就用,自己写一遍是为了理解原理,不是为了重复造轮子。我的原则是:核心逻辑自己实现,通用基础设施用成熟方案。比如向量检索的索引结构,自己实现一个暴力检索理解原理就够了,生产环境还是用成熟的向量库。

但有一个东西我建议自己写:评估脚本。因为评估逻辑和你的业务强相关,现成工具往往不够灵活。自己写一个评估脚本,想加什么指标就加什么指标,迭代起来最顺手。

7.2 数据清洗的投入被严重低估

大家聊AI工程都在聊模型、聊框架,很少有人聊数据清洗。但实际项目里,数据清洗占的时间经常超过一半。PDF解析出来的文本可能带乱码、页眉页脚、表格错位;网页抓下来的内容有导航栏、广告、无关链接。这些噪声不清理,后面分块和检索全是垃圾进垃圾出。

我的建议是,在数据清洗阶段多花时间,建立一套可复用的清洗规则。比如统一去除页眉页脚、合并被错误换行切断的句子、过滤过短的碎片块。这些规则一旦建好,后续所有文档都能受益。

7.3 日志和可观测性要提前埋

系统上线后出问题,如果没有日志,排查起来就是灾难。从第一天起就要把关键环节的日志埋好:每次请求的查询内容、检索到的文档ID和相似度分数、最终prompt的长度、模型输出的token数、各阶段耗时。

这些日志不仅能用于排错,还能用于分析。比如你发现某类查询的检索相似度普遍偏低,就知道这类查询需要特殊处理。可观测性不是上线后才考虑的事,而是从搭建第一天就要设计进去的。

7.4 版本管理不只是代码

AI系统里,除了代码要版本管理,数据、prompt、模型、索引都要版本管理。你换了一版分块策略,重新生成了索引,如果没记录,过两周你都不知道线上跑的是哪版。prompt改了一个词,效果变了,没有版本记录就无从对比。

我的做法是给每次重要的变更打一个版本号,记录变更内容、对应的评估指标。这样任何时候都能回溯,也能快速回滚到效果最好的版本。这个习惯看起来麻烦,但能帮你省下大量“到底哪版效果好”的扯皮时间。

8. 从能跑到好用:下一步可以往哪走

把上面这套最小系统搭完,你已经超过了大多数只会调包的人。但AI工程的深度远不止于此。如果还想继续深入,我建议往这几个方向走。

第一个方向是性能优化。研究KV缓存复用、连续批处理、投机解码这些推理加速技术,把吞吐和延迟再压一压。这些技术在大规模服务里收益非常明显。

第二个方向是多路召回与重排序。在向量检索和关键词检索之外,加入基于知识图谱的检索、基于规则的检索,再用一个重排序模型对多路结果统一打分。这是提升复杂场景效果的有效手段。

第三个方向是Agent化。让系统不只是被动问答,而是能调用工具、拆解任务、多步推理。这需要在编排层做大量工作,也是当前AI应用最活跃的方向。

但无论往哪走,底层那套“分块、检索、推理、评估”的基本功都是绕不开的。把地基打牢,上面的楼才盖得高。我自己从零搭过几套系统之后,最大的体会是:AI工程没有魔法,所有的效果提升都来自对每个环节的扎实理解和反复调优。那些看起来“聪明”的系统,背后都是这些笨功夫堆出来的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询