☰
从零搭建AI工程能力栈:RAG系统开发的技术路径与实践
2026/10/3 15:30:10 网站建设 项目流程

很多人第一次接触“AI工程”这个词,脑子里浮现的都是一堆云里雾里的概念,比如大模型、微调、RAG、Agent,然后下意识觉得这是算法研究员才能碰的东西。实际上,AI工程(AI Engineering)和算法研究完全是两条技能树。我过去这十来年,从前端到后端,再从后端一头扎进AI应用开发,最深的感触就是:AI工程本质上是“软件工程 + 机器学习 + 数据工程”的交叉学科,它解决的不是“模型怎么训练出来”的问题,而是“模型怎么用起来、用得稳、用得起”的问题。这篇博文,我就结合自己从零搭建AI工程能力栈的完整经历,聊聊我理解的“ai-engineering-from-scratch”,以及如果你也想走这条路,应该怎么下手。

这篇内容适合三类人看:一是被各种AI概念轰炸、想入行却不知道从哪开始的转行者;二是已经在写业务代码、想在项目中引入AI能力但怕hold不住的后端开发者;三是刚招了AI工程师、但不知道如何让团队高效协作的技术管理者。我会尽量用大白话,把我踩过的坑、验证过的路径、以及核心的实操细节都摊开来讲,希望能给同路人一个参考。

1. AI工程的整体技术全景与思路拆解

1.1 AI工程到底在解决什么问题

先说一个反常识的结论:AI工程里最不值钱的,反而是“训练模型”。早些年大家都迷信算法,觉得模型训练出来就万事大吉,但实际上一个模型从实验室到生产环境,中间隔着的不是“准确率提升1个点”,而是一整套系统工程。

我给一个生活化的类比。假设你开餐厅,菜谱(模型算法)只是基础,后厨怎么备菜(数据处理)、厨师怎么按标准流程炒菜(推理服务)、服务员怎么上菜(API网关)、顾客吃完怎么反馈优化(监控与迭代),这整条链路才是AI工程要管的事。单一某个环节再强,只要其他环节拖后腿,顾客体验照样崩。

所以,AI工程的核心目标有三个:

  • 可用性:模型能不能稳定对外提供服务,算力资源够不够,延迟高不高。
  • 可靠性:输入数据的分布发生变化时,模型会不会突然“失灵”;服务挂掉后能不能自动恢复。
  • 可维护性:模型版本怎么管理,特征怎么保障,线上出问题时怎么快速定位是模型原因还是数据原因。

这三件事,每一项都对应着具体的工程化手段,而不是靠拍脑袋或者堆硬件能解决的。

1.2 从AI到AI应用落地的完整链路拆解

我习惯把一条完整的AI应用链路拆成七个环节,任何一个环节出问题,整个应用都跑不起来:

  1. 数据获取与清洗:数据是一切AI应用的原材料,这步没做好,后面全是白费。
  2. 特征工程(或Prompt设计):决定把原始数据变成什么样,模型才能“看懂”,传统机器学习靠特征工程,大模型时代靠Prompt模板和思维链设计。
  3. 模型的训练、微调或选择:对于中小团队,大多数场景是用基座大模型 + 少量业务数据微调,或者干脆用开源模型做适配。
  4. 模型评估与准入:在把模型部署到生产环境前,要用一套评估集验证效果,测评不只是准确率,还有成本、延迟和安全维度。
  5. 模型部署与推理优化:在线的API服务、批处理任务、模型量化,都是这一环节的活。
  6. 应用集成与产品化:模型要和你的业务系统打通,封装面向用户的功能,这步需要大量的后端工程能力。
  7. 监控、反馈与持续迭代:模型上线只是开始,不仅监控系统状态,还要监控模型在真实数据上的表现,持续用新数据迭代。

我刚入行时最大的误区,就是过度关注环节3和5,也就是模型训练和部署,觉得这两块是“技术含量”最高的地方。后来被现实教育了很多次,才悟出:在工业界,数据环节(环节1、2)和监控迭代(环节7)往往是决定项目成败的关键,也是真正拉开普通团队和成熟团队差距的地方。

1.3 为什么选择“从零开始”这条路径

市面上已经有很多现成的框架,比如LangChain、LlamaIndex、LangSmith,或者云平台的一键部署工具。那为什么我现在特别强调“from scratch”也就是从零开始的路径?这绝不是为了故作高深,而是因为AI技术栈的“封装层”太厚了。

如果你一上来就用LangChain,你会发现确实很快,几个函数调用就能拼出一个基于大模型的问答应用。但一旦遇到问题,比如改Prompt怎么不生效、为什么某个回调没有触发、上下文管理到底怎么工作的,你会发现自己非常无助,因为框架帮你做的封装,同时也屏蔽了底层原理。这种“知其然而不知其所以然”的状态,在快速验证想法的时候没问题,但在生产环境一定出大问题,因为你没法排查问题,也没法从根源上做性能优化。

从零开始的路线,本质上是让你在“什么都不知道”的状态下,亲手走一遍AI应用的最小链路。哪怕你最终还是会使用框架,但到那时框架对你来说只是“提升效率的工具”,而不是“离了就不会写代码的黑盒”。这种底层的理解,是AI工程师跟“调包侠”的分水岭。

2. 核心技能栈拆解与工具选型要点

2.1 编程基础:Python是起点但绝不止于Python

几乎所有AI项目的首选语言都是Python,原因是它的生态实在太完善了:NumPy做数值计算、Pandas做数据处理、PyTorch做模型训练、FastAPI做服务化,几乎每个环节都有成熟的库。但如果你只会Python,在做AI工程时会经常卡壳,因为现实世界的AI系统从来不是孤立运行的。

我给你列一下我在实际项目中真正用到的编程语言和场景:

  • Python:数据处理、模型推理服务、实验脚本,80%的AI工作流都靠它。
  • SQL:数据提取、特征加工、结果分析,很多AI工程师居然不重视SQL,这在真实工作中非常吃亏,因为你的数据大概率在数据仓库里。
  • Bash / Shell:环境搭建、任务调度、日志排查,不会写Shell脚本,你连基础的数据清理任务都自动化不了。
  • Docker / Kubernetes配置:镜像构建、容器编排、资源管理,这决定了你的模型能否被团队里的其他人一键拉起。

如果你是完全的编程新手,我的建议是:别一上来就啃算法书,直接用项目驱动的方式,先写Python脚本处理一个CSV文件,再用FastAPI把它变成一个接口,然后慢慢扩展到其他技能。编程的“手感”比“概念”重要得多。

2.2 机器学习与深度学习:不需要成为数学专家

很多转行者最大的心理障碍是“数学不好”。这里我可以负责任地说一句:AI工程所需要的数学知识,远没有你想的那么高深。你不需要自己能推导复杂的损失函数,你只需要理解它们是什么、什么时候该用哪个、以及参数调整的大致方向。

以我个人的经验,真正高频使用的数学知识其实就这三块:

  • 线性代数:理解向量、矩阵运算,这是掌握Embedding向量的核心,也是理解Transformer里自注意力机制的基础。不需要会手算,能看懂Shape变化就够了。
  • 概率统计:理解分布、均值方差、置信区间,这在做评估和异常检测时特别有用。
  • 微积分(基础):理解梯度下降的直观概念,知道学习率是干什么的。至于链式法则、反向传播的具体推导,绝大多数AI工程师也用不到。

我的学习策略是“用到再学”。当你跑通了第一个模型,发现loss不下降,去查学习率是怎么影响更新步长的时候,你对梯度的理解会比死磕一个月教科书来得深刻得多。

2.3 工具链与平台:从零搭建你的AI地基

实操之前,先把地基打好。我用一套开源为主的工具链搭建了我的AI工程环境,整套组合灵活且零授权成本,非常适合个人学习和中小企业起步:

  • 开发环境:VS Code + Jupyter Notebook。Notebook做实验探索,VS Code写正式代码,两者互补非常顺手。
  • 数据生态:Pandas + Polars + SQLite。小数据量用Polars(性能好),关系型数据结构我用SQLite,后续要上生产再平滑迁移到PostgreSQL。
  • 模型框架:PyTorch + HuggingFace Transformers。PyTorch的生态和资料丰富度都远好于其他选择;HuggingFace提供了一个巨大的模型仓库,极大地降低了大家接触各种模型的门槛。
  • 服务化:FastAPI。自带OpenAPI文档、异步支持,结合uvicorn就能把模型包成一个服务,学习和生产都能用。
  • 容器化:Docker。约束环境、保持一致性,你想让别人或者另一台机器也能跑起来你的项目,Docker是最基本的保障。
  • 编排与调度:Kubernetes(生产环境)+ Airflow(任务调度)。这块学习曲线很陡,建议先搞懂Docker和单机部署,再逐步接触K8s,否则容易劝退。

工具选型的核心原则是“新手友好 + 社区活跃 + 能平滑迁移到生产”。我在搭建时,刻意忽略了诸如SQLite不该用于生产这类耳闻,因为对从零起步的场景,快速验证往往比一步到位更重要,先把流程跑通,再逐一替换成更专业的组件。

3. 实操过程:亲手搭建一个完整的AI工程最小系统

3.1 Step 1:定义场景与目标

纸上谈兵没意义,我直接以“搭建一个面向技术文档的智能问答机器人”为目标,演示从数据到服务全流程。为什么选这个场景?因为技术文档的数据干净、结构清晰、容易获取,而且问答这个任务可以直观感受到AI的能力边界,特别适合练手。

我们的任务定义是:输入一篇Markdown格式的技术文档,输出一个API接口,允许用户提问关于文档内容的自然语言问题,并得到带出处的回答。技术上,我决定采用“检索增强生成(RAG)”路线,也就是先根据用户问题检索最相关的文档片段,再把片段和问题拼在一起输入到大模型里,让它总结回答。

3.2 Step 2:环境准备与依赖安装

首先,创建一个干净的Python虚拟环境,这能避免不同项目之间的依赖冲突,是我一开始被教训过好多次才开始坚持的习惯。然后安装必要的软件包:

mkdir ai_engineering_demo cd ai_engineering_demo python -m venv .venv source .venv/bin/activate # Windows下用 .venv\Scripts\activate pip install fastapi uvicorn sentence-transformers faiss-cpu openai

说明一下这几个包的选择理由:FastAPI和uvicorn是服务层;sentence-transformers用来做文本向量化;faiss-cpu是向量检索库,我在这里用CPU版本做本地学习,生产时再替换成GPU或更专业的向量数据库;openai包里封装了调用大模型API的代码,方便我快速接入推理能力。

3.3 Step 3:数据处理与向量化

在RAG链路中,第一步是把文档切分成“块”(Chunk),并对每块进行向量化。这里有一个直接决定效果好坏的细节:切分策略。

我用一个最直观的方法是按标题层级切分,而不是固定字符长度。因为文档的语义边界通常在章节处,比如“## 3. 实操过程”下的内容围绕同一个主题。如果机械地每隔500个字符切一刀,很容易把一个完整的话题切得支离破碎。

下面是我用的核心代码:

import re from typing import List def split_by_headings(markdown_text: str) -> List[str]: """ 按Markdown的二级和三级标题切分文档, 把每个标题及下面跟着的内容拼成一个chunk。 """ # 找到所有标题及其行号 heading_regex = re.compile(r'^(#{2,3})\s+(.+)$', re.MULTILINE) matches = list(heading_regex.finditer(markdown_text)) chunks = [] for idx, match in enumerate(matches): start = match.start() end = matches[idx + 1].start() if idx + 1 < len(matches) else len(markdown_text) chunk = markdown_text[start:end].strip() if chunk: chunks.append(chunk) return chunks

切完之后,用sentence-transformers将每个文本块编码成向量,再将向量写入Faiss索引:

from sentence_transformers import SentenceTransformer import faiss import numpy as np model = SentenceTransformer('BAAI/bge-small-zh-v1.5') chunks = split_by_headings(open('docs/example.md', encoding='utf-8').read()) chunk_vectors = model.encode(chunks, normalize_embeddings=True) # 构建Faiss索引 dimension = chunk_vectors.shape[1] index = faiss.IndexFlatIP(dimension) # 内积(点积)索引,配合规范化等价于余弦相似度 index.add(np.asarray(chunk_vectors.astype('float32'))) # 保存元数据 import json meta = [{"text": c} for c in chunks] with open('chunks.json', 'w', encoding='utf-8') as f: json.dump(meta, f, ensure_ascii=False)

这里我特意选了中文向量模型bge-small-zh-v1.5,它对中文语义的理解能力强于很多通用模型,而且体积小(约100MB),适合本地学习和部署。如果你处理的文档是英文,可以换用bge-base-en-v1.5或e5系列,选择依据是尽量匹配你的语种,检索效果会差很多。

3.4 Step 4:检索与生成的完整实现

向量化完成后,就到了问答环节。RAG最核心的地方在这里:它不只靠模型“死记硬背”答案,而是每次回答都从你的文档里实时检索背景知识,再让模型基于检索到的内容作答。这一下就解决了大模型“编造事实”的常见问题,因为答案是来源可控的。

我用Faiss检索出与问题最相关的几个文档块,拼进Prompt里,再调用大模型API:

from fastapi import FastAPI from pydantic import BaseModel from openai import OpenAI import faiss, json, numpy as np app = FastAPI() client = OpenAI() # 如果调用OpenAI官方API,需要设置OPENAI_API_KEY环境变量 index = faiss.read_index('vector_index.faiss') meta = json.load(open('chunks.json', encoding='utf-8')) encoder = SentenceTransformer('BAAI/bge-small-zh-v1.5') TOP_K = 3 class Query(BaseModel): question: str def retrieve(question: str, k: int = TOP_K): q_vec = encoder.encode([question], normalize_embeddings=True) distances, indices = index.search(np.asarray(q_vec.astype('float32')), k) return [meta[i]['text'] for i in indices[0]] def generate_answer(question: str, context_docs: list): context = "\n\n---\n\n".join(context_docs) prompt = f"""你是一个严谨的技术顾问。请根据下面提供的文档片段,如实回答用户问题。 如果文档片段中没有足够信息,请明确回答“文档中未涉及该内容”,不要编造。 文档片段: {context} 用户问题: {question} """ response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "你是严谨的技术问答助手。"}, {"role": "user", "content": prompt} ], temperature=0.2, ) return response.choices[0].message.content @app.post("/qa") def qa(query: Query): docs = retrieve(query.question) answer = generate_answer(query.question, docs) return {"answer": answer, "sources": docs}

注意几个细节:检索出来的TOP_K我默认设成3,这个值太少了可能漏信息,太多了后面的模型会被无关信息干扰反而降低效果,建议在测试集上调;temperature设置成0.2是为了让回答尽量确定、少发散;Prompt里特别强调了“没有就直说”,这能显著降低模型的幻觉问题。

3.5 Step 5:容器化与一键启动

本地运行没问题后,就要把整个服务打包,让团队其他成员也能快速跑起来。Dockerfile的内容用最简单的方案:

FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]

构建并启动:

docker build -t ai-qa-demo . docker run -p 8000:8000 -e OPENAI_API_KEY=你的Key ai-qa-demo

这里有一个我在真实项目中反复踩坑的经验:不要在Docker镜像里包含模型文件,尤其是当你用的是几GB的大模型时。正确做法是把模型下载到单独的对象存储或模型仓库,在容器启动时拉取,或者挂载为外部卷。这样镜像体积小、启动快,而且模型更新时不用重新构建整个镜像。

3.6 Step 6:效果评估与迭代方向

系统跑通之后,你一定得做评估,不然根本不知道系统的真实水平。我在这个Demo里用的评估方法是:准备20个标准问答对,人工打分回答的完整性和引用准确性。我试过用大模型自动评估,但效果不够稳定,小规模人工评估又客观又省事。

实测结果给了我很深的印象:一开始检索准确率大约70%,原因是文档切分时有些表格和代码块被截断了,导致没检索到关键内容。我针对性地调整了切分逻辑:在切分前先把表格和代码块单独抽出来作为特殊Chunk,不参与正文切分;同时对标题层级做了一定程度的窗口合并,让每个Chunk包含更完整的上下文。这轮调整后,检索准确率提升到85%以上。这充分说明:在RAG系统里,数据管道的优化空间远比换一个大模型更大,也更便宜。

4. 常见问题与排查技巧实录

4.1 “相似度检索结果不相关”的排查思路

这是RAG系统最高频的问题。每次遇到,优先按下面这个顺序排查:

  1. 先看问题本身是否歧义,比如“它是什么”这种代指不清的问题,检索策略设计得再好也没用。
  2. 再看Chunk切分是否合理,检查你召回出来的文档片段是否真的包含了关键信息。如果答案分散在好几个不同的章节,检索目标本身就不清晰。
  3. 如果召回结果确实没有相关信息,就检查向量编码是否用了匹配的模型,比如中文问题配了英文模型,效果一定很差。
  4. 最后看是否需要给不同段落加权重,例如标题命中应该比正文命中更重要。这需要引入BM25关键词检索做融合,或者使用更高级的Rerank模型。

我自己的经验是:70%的“检索不相关”问题都不是模型不行,而是文档切块策略和检索前处理的问题,解决顺序不要搞反了。

4.2 模型回答“胡编乱造”时怎么办

AI应用的幻觉问题非常常见,我的处理原则从高优先级到低优先级排下来是:

  • 在Prompt里明确限定“只能依据上下文回答,不确定就直说”,这一步成本最低,能挡掉相当多的幻觉。
  • 在检索环节提高召回的准确性,如果相关上下文都没找到,模型就只能“自由发挥”了。
  • 把回答中的每个关键结论配上引用来源,让用户能自己判断可信度,这也能倒逼系统提升质量。
  • 如果场景很重要,就把温度降到接近0,并且用更严格的大模型做一次“事实一致性”审核。

4.3 服务延迟过高,如何优化

AI应用用户体验差,大部分原因是延迟。一个完整的RAG链路延迟大头通常在三块:向量编码(Encoder推理)、检索、大模型生成。我实际用的是这样几种优化招数:

  • 给向量模型也加上GPU或者用ONNX Runtime进行推理加速,别让编码速度拖后腿。
  • 对Faiss索引做量化处理,比如用IndexIVFFlat替代IndexFlatIP,牺牲一点召回率换大幅提速。
  • LLM生成阶段开流式输出(Streaming),用户先看到文字一个字一个字出来,整体的主观等待感会好很多——这一点常常被完全忽略,但体验提升立竿见影。
  • 如果文档规模不大,干脆全量加载进内存,避免每次问答都查数据库。

4.4 自主搭建过程中遇到的经典坑

我把这两三年实践里踩过、也看人反复踩的“经典坑”列成一个速查表,你对照着规避就能少走弯路:

坑的类型具体表现避免方法
Chunk切分不考虑语义一句话、半张表被切散优先按结构(标题、段落、表格)切分
向量模型不匹配语言中文文档用英文模型选同语言的向量模型,并测实际对齐效果
提示词不约束来源模型自由发挥导致胡编乱造Prompt里强制指定“只依据文档回答”
从不测试评估集上线后才发现效果烂小规模人工评估集至少准备30条,先过一遍
跳过Docker直接在本地跑换机器后依赖冲突、环境崩溃项目第一天就配好容器化环境
为了“灵活”引入超大框架框架学习成本淹没业务逻辑小项目先从零写起,理解后再用框架

4.5 关于算力和成本的实用建议

聊成本之前先说一件不少AI初学者的误区:把“用大模型”等同于“一定要买顶级GPU”。在绝大多数业务场景下,选择一条“适中模型 + 优秀检索 + 工程优化”的路线,成本会比直接上超大模型低一个数量级,这就是AI工程存在的重要价值。

在这个Demo的成本账是:向量化模型在CPU上运行,一次推理不到0.1秒;Faiss检索在几千个Chunk里查一次是毫秒级;真正花钱的是调用大模型API的每千tokens费用,其实即使每天跑几百次问答,成本也在可接受范围。

所以如果你在为企业设计AI功能,别一上来就规划数百万的预算。先用最小方案跑起来,用数据说话,再决定是否提高算力投入,这是理性且可持续的方式。

5. 从Demo到生产环境的进阶之路

5.1 数据层:从离线仓库到实时管道

在学习Demo里,我们用的是一个静态Markdown文件,向量库构建一次后就固定了。但在生产环境,文档是持续更新的,今天加了新章节,明天改了旧接口。这时候就需要一套数据管道:

  • 定期增量更新:用Airflow或Cron定时任务,扫描文档仓库的变化,对新增和修改的文档块重新向量化,并更新索引。
  • 元数据管理:每个Chunk除了文本内容,还要带上文档名称、版本、更新时间、作者等元数据。这对后续追溯来源、做权限控制至关重要,也能在检索后做精细过滤。
  • 数据血缘:记录“这个向量是从哪个文件的哪个段落生成的”,这能帮你快速定位线上问题究竟来自哪份文档的哪段内容。

我在接手过一个AI问答系统的时候,最痛苦的并不是模型效果差,而是文档更新了三版,向量库还是旧版,导致用户问到的全是过时信息。这让我养成了一个习惯:任何RAG系统上线第一天,就必须设计好“刷新”机制。

5.2 模型服务层:从单机到高可用

生产级模型服务需要考虑三件事:多副本、弹性伸缩、安全管控。

多副本是Kubernetes里做水平扩展的基础能力,把同一套模型服务部署成多个Pod,前面挂负载均衡,请求分发到不同副本上。弹性伸缩是根据请求量自动增减副本数,高峰时多开几个Pod扛住流量,低谷时缩回去节省资源,这个用Kubernetes的HPA(Horizontal Pod Autoscaler)组件能实现。安全管控则包括API Key鉴权、限流(Rate Limiting)、请求内容审计。模型服务一旦裸奔在公网上,分分钟会被刷爆配额,这不是危言耸听。

5.3 监控与评估层:没有监控的AI系统走不远

传统Web服务的监控看CPU、内存、QPS、错误率就差不多了,AI系统在这之上还额外关注数据分布漂移和结果质量。

我的经验是至少要监控四个指标:

  1. 响应延迟分布:不仅看平均值,还要看P95、P99,因为AI应用的延迟往往有长尾。
  2. 输入数据分布:比如问答系统里用户的句子长度、主题分布,一旦出现异常波动,往往预示业务变化或者垃圾流量攻击。
  3. 检索命中率:在日志里记录每次是否有文档被检索到,如果大量请求检索不到文档,说明知识库严重缺失。
  4. 用户反馈信号:点赞/点踩、复制行为、二次追问率,都是天然的隐式反馈通道,比任何离线评估都真实。

5.4 一个关键心态:AI工程是持续运营,不是一次性交付

把上面这些环节全部打通之后,你基本可以称得上“从零起步的AI工程入门者”了。但我要泼一盆经验冷水:AI系统的维护成本在相当长一段时间内都不会显著下降。因为现实世界的数据在变、业务需求在变、模型技术在变,任何一个变化都可能让昨天的效果变成明天的Bug。

这也是为什么我从不建议团队一次性追求“完美系统”。更符合现实的做法是:快速搭出第一版,用真实流量验证价值,然后持续监控、持续迭代。AI工程不是一个有终点线的项目,而是像运营一个餐厅,菜谱可以变、服务员可以换,但保证每一桌顾客都吃满意这件事,永远没有终点。

写在最后:我实践中的一点私人体会

如果让我给正在从零起步学AI工程的朋友一句忠告,我会说:“别等准备好了再出发,先做一个丑但能用的东西。”我见过太多人花三个月刷课、记笔记、背概念,却始终没跑通过一个哪怕最简单的问答接口。真正的学习密度,发生在你动手搭建、发现bug、查阅文档、逐步优化这个反复循环里。

还有一个小习惯特别值得分享:我会在每次完成一个小项目后,专门写一份“复盘文档”,记录三类内容:当时卡住我的问题是什么、我通过什么线索找到的解决方案、如果重来一次我会在哪个环节提前做什么准备。这份文档比任何课程笔记都珍贵,因为它记录的就是你自己的能力增长轨迹。也很建议你试试在社区里公开分享你的项目过程和踩坑记录,这是我实践下来提升最快的方式,没有之一。

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

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

立即咨询