去年有段时间我一直在纠结一个问题身边很多朋友喊着要转行做 AI结果一上来就抱着大模型论文啃或者收集了一堆别人的 demo 代码跑一遍最后连一个能稳定运行的接口都交不出来。我自己从传统后端转过来踩了整一年坑才摸清楚所谓的 ai-engineering-from-scratch本质上不是学几个模型调用而是一条从数据处理、模型选型、检索增强到部署评测的完整工程链路。这篇文章我想把那一年里沉淀下来的方法论、实操步骤和血泪教训一次性讲清楚给真正准备从零开始的人一条可以照着走的路。这篇文章适合两类人一类是有编程基础但没碰过 AI 的新手另一类是已经会调 API 但总觉得项目很飘、交付没底的开发者。我会从整体设计思路讲起把每个环节的为什么讲透再用一个完整的 RAG 知识库问答系统作为贯穿案例最后附上我实测中遇到的高频问题排查表。看完你应该能独立规划并落地一个中等复杂度的 AI 工程项目。1. 从零起步这个项目到底在解决什么问题1.1 我为什么说AI工程不等于会调模型很多人对 AI 工程的第一印象是写个提示词、调一下参数、把模型接口接进来。这种认知在个人玩玩的场景下勉强够用但放到真实业务里很快会暴露问题。我见过一个团队花两周调提示词最后效果还是时好时坏根本原因在于他们跳过了数据清洗、检索召回质量、评测闭环这些真正的工程主体。AI 工程的核心矛盾从来不是模型能力不够而是模型能力与业务数据之间的最后一公里没有被工程化地解决好。从系统视角来看一个可交付的 AI 应用至少包含五个层次数据层采集、清洗、切分、模型层基座选择、微调策略、推理部署、增强层RAG、Agent、工具调用、服务层API 封装、并发治理、缓存、评测层指标设计、回归集、线上监控。这五个层次缺一个项目都能跑起来但都跑不长久。我现在判断一个候选人或者一个项目是否算是AI 工程就看它有没有把这几层完整地串起来。打个比方调模型像是拿到了一台好发动机但AI工程是做整辆车得解决燃料供给数据、传动系统检索与提示词编排、仪表盘监控评测、还有定期保养迭代机制。只盯着发动机的功率车照样开不上路。1.2 目标人群与前置条件如果你正准备从零开始先别急着囤课对照下面这个清单看一下自己站在哪里。最理想的前置条件并不多扎实的 Python 基础能用类组织代码、能写装饰器、懂生成器、熟悉 Linux 基本操作、掌握 SQL 或 Pandas 之类的东西做数据操作。这些都不难难的是很多人在这三步没走完的时候就去碰大模型训练导致后面全是空中楼阁。我的建议是给自己定一个两个星期完成前置补齐的硬性窗口期。每天用两小时刷 Python 核心语法剩下时间用真实数据比如导出自己的浏览器历史记录或者电商订单做清洗和统计分析。这个阶段的目标不是学会所有 API而是建立数据是可以被程序化处理的感觉。实测下来这个前置准备比后面任何课程都值钱。前置条件不需要数学多好但建议掌握基本的概率直觉比如分布、均值、方差以及独立同分布这个概念。为什么提这个因为后续做模型评测时你会反复和数据分布打交道没有这个直觉你连训练集和测试集为什么要分开都理解不透。1.3 整体学习路径的四个阶段我把从零到可交付的路径压缩成四个阶段每个阶段都有明确的产出物而不是以学完了多少章为标准。第一阶段是基础工程能力产出物是一个能自动定时爬取数据、清洗入库的 Python 脚本第二阶段是模型应用能力产出物是一个基于开源模型 API 的问答 Demo要求做到流式输出和并发调用第三阶段是检索增强能力产出物是带向量检索的 RAG 系统知识库你自己选一个熟悉的领域比如你公司的产品手册、或者一个开源项目的文档第四阶段是部署评测能力产出物是这个系统的评测报告和线上监控面板。这四个阶段正好对应了我前面说的五个层次只是把增强和部署做了前后编排。执行的时候有个关键心法每个阶段必须跑通再往前走而不是看完再动手。我见过太多人把四个阶段的书都翻完了代码却一行没写这种学习方式在 AI 工程领域基本无效因为模型行为和文档描述经常不一致只有实测才能建立真实体感。2. 核心技能栈拆解每个环节该学什么、为什么2.1 基础设施Python 与工程化能力AI 工程里的 Python 和你在教程里学的 Python 是两回事。教程教你语法工程要求你写出的代码能被别人维护、能处理异常、能支撑并发。我强烈建议从第一天就用venv管理环境用pyproject.toml或requirements.txt锁定依赖版本。这看起来是小事但模型生态的依赖冲突极其严重动不动就是transformers和torch版本打架没有环境隔离你会在装包上浪费一周。工程化还有一个容易被忽视的环节日志。在 AI 应用里日志不只是排查错误用的更是评测和迭代的数据来源。我在每个项目里都会给所有外部调用模型接口、向量库、检索接口统一打上耗时、参数、返回摘要三要素日志。上次排查一个线上回答变差的问题就是靠翻日志发现某个数据源格式悄悄变了导致召回质量骤降。没有日志这种问题只能靠猜。异步编程是另一个必须尽早掌握的技能。真实业务的模型调用动辄一两秒如果同步处理单机 QPS 根本撑不起来所以asyncio和httpx的异步客户端是必需品。我建议你做一个压力小实验写一个同步版 Flask 接口调用模型再用FastAPI加异步改造对比一下同样的并发下响应时间和吞吐量这个实验做完你就理解为什么 AI 服务几乎都用异步框架了。2.2 模型层从深度学习基础到大模型应用很多人问我深度学习基础到底要学到多深我的答案很反直觉前向传播、反向传播、损失函数、优化器的基本原理搞懂就够了不需要能手推 Transformer 公式。为什么因为 AI 工程的重点是应用和集成而不是发明模型。你需要理解的是一个模型的能力边界在哪里、什么输入会触发什么行为以及为什么同一套参数在换一个领域后效果全变。大模型应用层有三板斧提示词工程、上下文管理和工具调用。提示词工程看起来简单实际上是个迭代活我后面会单独讲。上下文管理则涉及你喂给模型的文本量长文本带来的注意力分散和信息稀释是真实存在的所以才有 RAG 这种先检索再生成的做法。工具调用Function Calling则把模型从文本生成器变成任务调度器这是 Agent 类应用的基础。如果你真的想深入模型层一层我建议做一个小微调项目但不要用全量微调用 LoRA。选一个开源基座拿一万条领域数据做指令微调对比微调前后同一个问题的回答差异。这个过程能让你直观感受到模型参数调整到底改了什么也能体验数据质量对效果的巨大影响——微调效果差的时候九成原因是数据烂而不是参数不对。2.3 数据与向量检索RAG 的骨架数据是 AI 工程里最不值钱又是最值钱的东西。说不值钱因为网上到处是开源数据集说最值钱因为业务场景里的高质量数据全在你自己手里而这些恰恰决定了系统的上限。我建议从零开始学习时先建立一套自己的数据处理流水线包含去重、格式清洗、敏感信息脱敏、质量过滤四个步骤。特别提醒脱敏一定要做别等出事再补。向量检索今天看起来是标配但真正决定检索质量的不是向量模型用得多好而是文档切分的合理性。我见过很多新手把几万字的文档直接整篇向量化结果检索出来的片段要么太粗要么太碎。我的实践经验是先按文档天然结构切分标题、段落再按固定窗口做重叠切分重叠量控制在 10% 到 20% 之间。这个比例不是拍脑袋定的太小会让上下文断裂太大会引入噪声。选择向量数据库时也别迷信。小项目用sqlite-vss或者chroma就够了上了千万级向量再考虑milvus或qdrant。我个人的迁移经验是先把业务逻辑和存储层解耦定义统一的检索接口后面换库只需要改实现不用改业务代码。很多人一开始图省事把向量库调用的代码写得到处都是等到数据量上来要迁移时想死的心都有。2.4 部署与评测让系统真正可交付部署是整个 AI 工程里最容易被低估的环节。模型推理不像普通 Web 服务它在显存占用、延迟、吞吐上有完全不同的特征。初次接触时先把四个关键指标搞清楚首 Token 延迟TTFT、生成延迟TPOT、并发吞吐和显存占用。这四个指标直接决定你的服务能不能扛住业务流量。评测则是另一个容易被糊弄的环节。很多团队上线前口头说效果还行上线后一塌糊涂就是因为没有量化指标。我的做法是维护一个固定的评测集包含至少 100 条真实问题对每个问题标注标准答案或者关键评分点每次改动后跑一遍用回答准确率、检索召回率、无效回答率、平均延迟四个指标做回归对比。这个评测集是 AI 工程里的单元测试没有它迭代就是盲人摸象。3. 实操从零实现一个 RAG 知识库问答系统3.1 系统架构与组件选型现在我们把前面所有的知识串起来落地一个具体的项目基于 RAG 的知识库问答系统。我选的场景是公司内部的产品文档问答你也可以换成任何你熟悉的领域。整体架构是标准的三段式离线处理链路把文档切分、向量化后存入向量库在线查询链路把用户问题向量化后检索相关内容生成链路把检索结果和问题组装成提示词交给模型输出答案。组件选型我的推荐是Python 3.10FastAPI 做服务框架向量化用开源 embedding 模型向量库用 chroma项目初期最省事模型推理用开源模型的 API 服务本地部署方案后面讲调度编排直接用原生 Python 代码不引入 LangChain。为什么不用 LangChain不是它不好而是对新手来说它把太多细节封装掉了出了问题你根本不知道是检索的锅还是提示词的锅。先用原生代码跑通一遍再看框架源码你会对 RAG 有完全不同的理解。下面是一个最小架构的服务端骨架我直接给出来你可以照着改from fastapi import FastAPI from pydantic import BaseModel from retriever import retrieve from generator import generate app FastAPI() class Query(BaseModel): question: str top_k: int 5 app.post(/qa) async def qa(query: Query): docs retrieve(query.question, query.top_k) answer generate(query.question, docs) return { answer: answer, sources: [d[source] for d in docs], }3.2 数据清洗与切分策略数据准备阶段我拿一份真实的产品手册来做示范。原始文件可能是 PDF、Word 或者 Markdown第一步先统一转成 Markdown 文本。这个过程比想象中坑多PDF 里的表格会被打散图片里的文字根本抽不出来所以必须人工抽检。我的经验法则是随机抽 3% 的文档做人工核对如果表格结构错乱超过 10%就要换解析工具或者走 OCR。清洗完成后进入切分环节。我的切分逻辑分三步先按一级标题拆成大块再检查每块是否超过 800 字的窗口上限超过的按段落继续切最后为每个切块补上标题前缀比如第三章-安装说明-第2节-环境要求。加前缀这个细节能显著提升检索精度因为很多切块单独看是语义不完整的前缀提供了定位信息。切分参数我实测常用的组合是块大小 500 字、重叠 80 字。这个组合在绝大多数说明文类文档上表现稳定既不丢上下文又不会引入过多噪声。建议你准备一份小测试集跑不同块大小300、500、800下的检索命中率对比用数据决定自己的参数。切分代码如下def split_document(md_text: str, chunk_size: int 500, overlap: int 80) - list[str]: paragraphs [p.strip() for p in md_text.split(\n\n) if p.strip()] chunks, current [], for para in paragraphs: if len(current) len(para) chunk_size and current: chunks.append(current) current current[-overlap:] if overlap else current para \n if current: chunks.append(current) return chunks3.3 向量化与检索实现向量化的核心是选择 embedding 模型。我的选择标准有三条中文语义理解能力、向量维度不要太高太高意味着存储和计算成本上升、社区生态活跃。在实际项目里我会在本地跑一个候选模型的对比测试用一组同义改写和跨主题干扰的数据集看检索排序的稳定性。这个测试花不了多少时间但能避免上线后才发现向量模型不贴合业务。检索实现分成两个阶段先用向量相似度召回 top 50 候选再做重排。为什么多这一步因为向量相似度是语义近似但近似不意味着有用很多召回的片段虽然语义接近用户问题但并没有直接回答问题。重排环节我用一个简单的 RRFReciprocal Rank Fusion加上规则过滤规则包括片段的标题前缀必须匹配问题中的实体词、片段不得重复来自同一文档段落。这些规则看起来粗暴实测能把无效召回率降低三分之一。向量检索的代码骨架如下注意我用了统一的检索接口方便后面换向量库import chromadb class VectorRetriever: def __init__(self, collection_name: str, embedding_fn): self.client chromadb.Client() self.collection self.client.get_or_create_collection(collection_name) self.embedding_fn embedding_fn def add_docs(self, chunk_ids: list[str], texts: list[str], metadatas: list[dict]): vectors [self.embedding_fn(t) for t in texts] self.collection.add(idschunk_ids, embeddingsvectors, documentstexts, metadatasmetadatas) def retrieve(self, query: str, top_k: int 10): q_vec self.embedding_fn(query) return self.collection.query(query_embeddings[q_vec], n_resultstop_k)3.4 生成环节与提示词编排检索到的内容最后要交给生成模型这一步的核心是提示词编排。我踩过最大的坑是提示词里什么都想要既要求引用来源又要求输出格式还要求拒绝回答与文档无关的问题结果模型无所适从。后来我总结出来的原则是提示词只做三件事——定义角色、给出任务约束、明确输出格式其他一律交给模型自己发挥。一个我实测稳定的知识库问答提示词模板长这样你是产品文档答疑助手。只依据提供的文档内容回答用户问题。 如果文档中没有相关信息直接说文档中未找到相关内容不要编造。 文档内容 {context} 用户问题{question} 要求回答时先给出结论再用引用片段佐证控制在200字以内。注意上下文组装顺序相关片段要按召回分数从高到低排列同时把最相关的片段放在离问题最近的位置。大模型对长文本的注意力分布不均开头和结尾的内容往往被赋予更高权重所以关键内容要么放最前、要么放最后别埋在中段。我在多个开源模型上验证过这个现象调整上下文顺序后答案命中率平均能提升 5 到 8 个百分点。3.5 评测闭环与迭代系统跑通后立刻进入评测闭环不要急着优化。我的做法是准备三个测试集合冒烟集10 条验证基本功能、回归集100 条覆盖文档各章节、压力集200 条包含模糊问题和越界问题。每次改代码先跑冒烟集再跑回归集。回归集效果不降才允许继续做优化否则先复盘改动影响。评测结果除了回答准确率一定要记录检索命中率和无效回答率。我见过太多项目回答很漂亮追问才发现靠的是模型幻觉而不是检索结果。把检索命中率和回答质量分开统计能帮你定位问题到底出在检索环节还是生成环节。这是 RAG 系统迭代最重要的诊断手段。迭代顺序也有讲究先优化检索命中率上去了再谈生成再优化提示词最后才考虑微调模型。很多团队顺序搞反一上来就微调结果检索到的资料本来就是错的微调再好的模型也只能一本正经地胡说。4. 工程化落地部署、性能与成本4.1 模型服务化与推理优化当知识库问答系统在本地跑通后下一步是把它变成真正能对外提供服务的系统。模型服务的部署方案需要根据你的资源情况来定有 GPU 资源就本地化部署可控性最强没有就调云上模型 API胜在稳定省心。我建议新手阶段直接用开源模型的托管 API 先跑业务等确实有私有化部署需求了再上推理服务框架比如 vLLM 之类不要一开始就在部署上过度投入。推理优化的核心思路有三个批量推理、缓存和量化。批量推理是最容易见效的手段把多个用户的请求攒在一起打包发给模型吞吐量能成倍提升代价是单请求延迟略微升高。缓存则是把高频重复的问题答案缓存起来我实测在知识库问答场景中大约有 20% 的问题是高度重复的加一层 Redis 缓存就能省下 20% 的模型调用成本。量化要放在最后考虑。它把模型权重从高精度浮点数压缩成低精度能显著降低显存占用和推理延迟但会有少量效果损失。我的经验是先在你自己的评测集上做量化前后对比如果准确率下降在 2% 以内就能接受。不要盲信量化无损的说法在部分领域任务上量化带来的退化是很明显的。4.2 性能瓶颈与系统监控我接手过几个性能问题最后定位到的瓶颈五花八门有的是 embedding 模型串行调用太慢有的是向量库没用索引导致全表扫描有的是生成模型上下文太长导致首 Token 延迟爆炸。所以性能优化第一步永远不是猜而是先把调用链路的耗时打点统计出来。我给每个接口加了三个关键耗时指标检索耗时、生成耗时、总耗时用日志聚合出 P50、P95 两个分位数。监控面板我建议包含四个维度流量维度QPS、请求成功率、性能维度P95 延迟、首 Token 延迟、质量维度无效回答率、用户反馈率、成本维度单次请求成本、每日总消耗。前两个维度是常规运维监控后两个维度是 AI 系统特有的缺了质量维度和成本维度你根本不知道系统线上值不值得继续投入。这里有个针对性的建议给生成模型加拒绝回答的监控项。在评测集里看到无效回答率升高往往意味着线上数据分布发生了漂移或者某个上游数据源出了问题这比监控服务器 CPU 更能预警业务风险。4.3 成本控制策略AI 工程的成本大头永远是模型调用所以成本控制的核心是从架构上减少无谓调用。我的策略有三条。第一能检索先检索把检索结果对模型可见性的判断前置如果检索结果明显与问题无关直接返回未找到相关内容不调用生成模型第二对简单问题走小型快速模型只有复杂问题才走大型模型做一个基于问题长度和关键词的路由层就能实现第三给每个用户或部门设置配额防止个别异常流量把预算打爆。实测下来这三条策略能把模型调用成本压到原来的三分之一到一半。其中路由层收益最大因为你用长问题的比例通常远比短问题低大量短问题调用贵模型本身就是浪费。路由规则我写得非常简单问题小于 20 个字且包含明确的文档关键词走小模型否则走大模型。别小看这个粗糙的规则它带来的成本优化立竿见影。5. 常见问题与排查技巧实录5.1 检索不到相关知识先检查切分质量检索不到相关内容是 RAG 系统最高频的问题我遇到十个项目有八个先来找我聊这个。绝大多数情况下根源不在向量模型而在切分太粗导致语义被稀释或者查询表述跟文档表述差异过大比如用户写退货流程文档里写的是退款说明。排查步骤我固定执行三步第一步直接打印检索结果看召回了什么第二步把用户问题和召回片段做人工对比判断到底是语义鸿沟还是切分问题第三步分别用关键词重写查询和缩小切分窗口两个实验来验证假设。针对语义鸿沟我推荐最轻量的解法是查询改写把用户问题先交给模型改写成一到三个更具体的检索子查询再分别检索最后合并。这一步成本不高但提升明显。针对切分问题则回到我们前面说的块大小和重叠参数拿带标注的测试集重新调参即可不需要改架构。5.2 回答幻觉严重别急着骂模型幻觉几乎是所有 AI 应用的必经之痛。但我在排查了多个项目后发现幻觉的责任链通常指向检索质量而不是模型本身。最典型的场景是检索到的片段包含正确答案但提示词没有强调只依据文档内容回答也没有处理文档无答案时如何回应于是模型自由发挥。先检查提示词里的约束是否真正写清楚了再检查上下文里是否有太多不相关内容干扰模型判断。如果提示词和检索都没问题还出现幻觉下一步是检查上下文顺序把重点信息从中间挪到开头或者末尾。最后才考虑提高模型规模或换更强的模型。我见过一个项目换了三个模型都没解决幻觉最后发现是评测集里文档内明明有答案的题只占四成剩下六成是文档里根本没有答案的题模型面对这种题无论怎么调都不可能答对只能靠拒绝回答兜底。所以幻觉治理的起点是先搞清楚你的问题集里有多少是真实可答的。5.3 提示词越调越乱建立版本管理提示词迭代是很日常的操作但很多人都是直接在代码里改改上十来版后彻底失控不知道现在线上跑的是哪一版也不知道某个老版本为什么效果更好。我的做法是给每个提示词版本建立一个独立文件命名包含日期和改动说明并且每次改动都同步在评测集上跑回归记录指标变化。这样下来提示词也变成了可以回溯的代码资产。我还习惯在提示词里加一个隐藏的格式标记比如要求模型输出时带上版本号便于线上日志里直接识别当前跑的是哪个版本。这个办法听起来有点土但排查线上问题时特别好用一眼就能判断生成结果是不是来自最新的提示词省掉了反复确认的麻烦。5.4 评测过拟合与数据泄露评测集用得久了会慢慢出现过拟合现象模型和提示词可能已经对评测集里的提问模式产生了针对性的适应回归集上的指标很漂亮但线上真实问题效果平平。这是 AI 工程里最难察觉的问题之一。解决办法是定期扩充评测集每两周从线上真实日志里抽一批新问题加进去同时把老问题随机淘汰一部分保持评测集的新鲜度。数据泄露则是另一个隐蔽问题。如果你在清洗语料时不小心把测试集的答案也写进了知识库那评测指标的含金量就报废了。我的规范是知识库数据和评测集数据必须分目录存放并且用脚本做交叉检查确保评测集的内容没有出现在知识库中。这个检查写起来很简单但能避免你在错误的数据上浪费一个月。根据我做完整个项目的经验ai-engineering-from-scratch 这条路最难的其实不是学技术而是建立端到端交付的意识和节奏。很多人栽在同一个地方学的时候贪多嚼不烂做的时候又恨不得一步到位。我最后想分享的一个小技巧是把最终项目拆成三个连续的小里程碑每个里程碑必须能在两小时内演示出结果这样你的学习动力和交付信心才能一直在线。技术会过时但把问题拆小、把评测做实、把闭环跑通这套方法论换到任何一个新技术上都还能用。
阅读完成 · 觉得有帮助?