
我做AI工程这条路是从一次非常狼狈的演示开始的。当时领导要求把一个开源大模型接到内部工单系统上我整整调了三天提示词结果演示时模型回复了一长串道歉话术场面极其尴尬。那之后就逼着自己把调用模型API这件事从野路子玩成了体系化工程。如果你现在也想从零走进AI EngineeringAI工程这条赛道或者已经踩过几个坑还想继续走这篇文章会把我走过的完整路径、关键选型逻辑、实操细节还有踩坑记录一次性讲清楚。我会尽量说人话不搞那种从入门到放弃的教程而是给你一条真的能走通的路。适合看这篇文章的人有基本Python基础、想做大模型应用但还没系统地建立AI工程知识框架的开发者后端想转AI应用方向的工程师还在用调Prompt碰运气方式写应用、希望把流程做得更可靠的产品技术同学。内容会从概念梳理讲到代码实现再讲到本地部署和排查你完全可以顺着章节往下看把每一步落到你的机器上跑一遍。1. 先搞清楚AI Engineering到底在解决什么问题1.1 它不是调API而是驯服不确定性很多人在刚接触AI工程时会有一个误解觉得我会requests.post调一下OpenAI接口会写Prompt就是AI工程师了。说实话这种水平做个小玩具没问题但离工程两个字还差得很远。我在实际项目里体会最深的一点是传统软件工程的逻辑是确定性的——你输入A代码输出B一切可预测、可测试。但大模型应用是概率性的——你输入A模型可能输出B也可能输出C甚至输出一段自带格式错误的文本。所以AI工程的核心不是把模型接进来而是把这种不确定性给治理住。你要设计一套完整的流程让模型在绝大多数情况下都能稳定输出你要的东西输出不理想时系统有降级策略模型抽风时有兜底逻辑。这些技术点串起来才叫AI工程。举一个我常用的类比传统开发像是盖砖混结构的房子每块砖的尺寸你都清楚AI工程更像是浇筑混凝土——材料本身是流动的你需要靠模板提示词结构、流程约束把它定型而模板的搭法恰恰是这个领域最值钱的经验。从热搜词里你也能看出大家关心什么AI Agent智能体、Prompt Engineering提示工程、RAG检索增强生成、本地部署。这些都不是孤立的技术点它们是围绕如何把大模型稳定地嵌入业务系统展开的。AI工程要解决的就是把这些点串成一条端到端的流水线。1.2 它和传统后端开发、数据科学的边界怎么划我做这个方向之后经常有人问这到底是后端活还是算法活我理解是这样方向关注点交付物传统后端接口、数据库、事务、并发稳定运行的Web服务数据科学/算法模型效果、指标、训练流程高精度的模型或分析结果AI工程模型能力如何被业务稳定调用可维护、可观测的AI应用系统数据科学更关心模型的准确率怎么提上去AI工程更关心模型效果还行的情况下系统能不能扛住线上流量、能不能做流式输出、上下文一长会不会崩。后端开发关心通用的中间件和架构而AI工程要在通用架构之上额外处理模型输入输出本身带来的问题——比如用户的提问怎么改写才能命中知识库、检索出来的片段怎么组装模型才不会胡编、模型的返回怎么解析才能保证JSON格式不错乱。这个边界感很重要。我见过不少人转行AI工程一上来就死磕模型训练和微调方向就偏了。AI工程的主战场在应用层和推理层它的核心技术栈是提示工程、工具调用、检索管线、输出解析、评估和部署优化。知道自己在哪个层干活才能把时间花在刀刃上。2. 从零开始的完整学习路径按这个顺序走三个月见效2.1 先把基础技术栈补牢别急着上大模型先确认你手上有这几个工具Python基础至少要看得懂类、装饰器、类型注解、yield生成器。AI应用很常见的一种写法是用yield做流式输出你不懂生成器连流式响应的代码都会读不懂。OpenAI SDK的调用方式不只是OpenAI现在很多国产模型也兼容这个SDK风格会一个就通吃一大片。Git和虚拟环境用python -m venv .venv建环境用git init管理代码这是基本的工程素养不然代码改着改着就成一坨烂摊子。FastAPI基础只需要会定义路由、用Pydantic模型做请求体校验、能跑起一个简单的服务。FastAPI是目前AI应用层最主流的选择异步支持和类型提示跟AI生态配合得很好。这些基础如果你完全从零开始花两三周扫一遍就够了不用啃大厚书遇到不懂的语法直接查文档。关键是不要停在看要动手把每一个示例自己在本地跑出来。我在带人入门的时候反复强调AI工程是泡出来的手艺不是看出来的知识。你亲手跑通一遍API调用比看十篇教程都有用。2.2 Prompt Engineering这是你和大模型沟通的底层语言很多人对提示工程的印象是一句你很聪明就能把模型调教好那就大错特错了。真实场景里我需要把提示词当成一套结构化协议来写。一个可靠的生产级Prompt通常包含这些模块角色定义让模型明确你是谁你是某公司的售后客服助手。任务目标让模型知道你要干什么根据提供的知识片段回答用户问题。约束条件让模型知道哪些事绝对不能做如果知识片段中没有相关信息明确回答知识库中未找到禁止编造。输入数据格式明确什么位置开始是用户问题什么位置是检索到的知识片段。输出格式有结构要求的直接要求输出JSON并给出字段说明。再配合few-shot给一两个示例和Chain of Thought让模型先思考再回答一次调用效果就能提升一大截。还有一点Prompt也要有版本管理。我现在的项目里每个Prompt都单独放在一个目录下用Git来管理版本改了什么一目了然。你想想如果Prompt全写在代码里每次微调之后线上效果变了你不知道是代码导致的还是提示词导致的排查起来会非常痛苦。写Prompt还有一个避坑技巧不要只在一个完美的示例上测试要多准备几个边界案例。比如空输入、超长输入、包含恶意指令的输入、包含与主题无关内容的输入。大模型应用一个很常见的隐患就是提示词注入——用户可能故意在问题里加上忽略之前的指令之类的话来绕过系统约束。把这类边界案例写进测试集每次改Prompt都跑一遍比什么防护都实在。2.3 RAG让模型拥有私有知识当你要做的应用必须回答包含公司内部文档、产品规格、专业资料的问题时纯粹靠Prompt去塞上下文是不行的。这里就涉及RAGRetrieval-Augmented Generation检索增强生成。它在AI工程里的地位几乎等同于数据库在后端里的地位。RAG的基本流程不复杂把文档切块 → 通过Embedding模型把每个块变成向量 → 用户提问时把问题也变成向量 → 在向量库里做相似度检索 → 把命中的文档块和问题一起交给大模型回答。但这个流程每一步都有讲究切块切多大我建议按内容语义来切而不是死板地按固定字符数。优先保留章节结构比如按Markdown标题、按段落切每个chunk控制在300~500个字左右。切小了检索时缺乏上下文切大了容易混入不相关内容、还浪费token。Embedding模型怎么选中英文混合场景建议用bge-m3这类支持多语言的模型纯英文场景选择面更广。不要盲目追求最强要看你部署环境的硬件能否跑得动。检索不只要向量。纯向量检索容易漏掉关键词命中但语义距离稍远的文档。更可靠的做法是混合检索BM25关键词向量检索各取一批再通过重排序模型比如bge-reranker把合并后的结果重新打分取最靠前的top-k。RAG工程里还有一个很容易被忽略的点上下文组装格式。检索到的文档块与用户问题的界限要清晰否则模型分不清哪些是参考资料哪些是闲聊内容。我常用的一套格式是请根据以下资料回答用户问题。 资料开始 [1] ... [2] ... 资料结束。 用户问题... 请基于资料回答问题如果资料中没有依据请如实说明。2.4 AI Agent从一问一答到让模型干活如果RAG是AI工程里的数据库那Agent就是业务逻辑。它的核心思想是让模型在回答过程中调用外部工具查天气、查订单、发邮件、执行代码再根据工具返回的结果决定下一步动作。这个方向是目前ChatBot走向生产力工具的关键。做Agent绕不开Function Calling函数调用。简单说就是在调用大模型时你把可用的工具以JSON Schema的形式告诉模型模型会在输出里返回应该调用哪个函数、参数是什么你的程序再负责真正执行这个函数把结果返回给模型让模型生成最终回答。这个机制非常实用但工程化的时候有几个坑工具描述要写清楚尤其参数的格式。模型是根据描述来选函数的描述模糊了它就选错。比如获取天气要写明参数是city还是location省份、城市要不要分开。必须有循环上限。模型可能会在工具之间反复横跳或者一次对话触发十几次调用。一定要在代码里设置最大迭代次数比如5轮超出就主动终止不然你的token账单会很难看。工具调用的结果要经过处理再给模型。原始返回可能是超长JSON直接塞进上下文会稀释模型的注意力。我一般会在工具函数里先做一次提炼只保留真正需要让模型知道的关键字段。3. 动手做一个完整项目内部知识库问答助手3.1 项目选型为什么首选问答机器人而不是智能助手对于从零起步的人来说我最推荐的项目不是AI Agent而是一个知识库问答助手。原因很简单Agent涉及的工具调用和循环控制对新人来说状态管理太复杂容易死于半途。而知识库问答助手的技术栈恰好在够用和有深度之间它需要你做文档处理、Embedding、向量检索、Prompt优化、流式输出、评估这些全是AI工程的核心基本功做完这个项目你可以直接横向扩展去做Agent。我建议的项目目标做一个本地运行的Web服务用户输入问题后它能基于一份给定的技术文档精准回答并且在回答末尾列出参考了哪几个文档片段。不要小看这个需求它已经覆盖了AI应用产品化的80%关键路径。3.2 整体架构与关键依赖这个项目的架构分成两条主线预处理线离线把PDF/Markdown文档加载进来 → 清洗 → 切块 → 向量化 → 存入向量数据库。这条线只在文档更新时跑。问答线在线用户提问 → 改写/直接向量化 → 检索 → 重排序 → 组装Prompt → 调用大模型 → 流式输出。技术选型上我推荐这一套主要看重生态成熟和部署简单向量数据库用chromadb或lancedb本地文件型不需要单独起服务对新手最友好。Embedding初学本地跑可以先用sentence-transformers里的bge-small-zh-v1.5效果够用显存占用低。LLM如果本地显卡允许7B~14B量的量化模型足够没有GPU的就调云端的兼容OpenAI接口服务。主框架FastAPI LangChain或者纯手动组装不依赖框架。这里我多说一句学习阶段强烈建议先纯手写一遍RAG流程不要直接上框架。等你手动组装过一遍向量化→检索→组装Prompt整个流程再去用LangChain之类的东西你才能真正看懂它帮你做了什么出了问题也好排查。3.3 核心代码逐段拆解文档切块阶段我的一个核心思路是按结构切而不是按字符硬切。我会先用正则把Markdown文档按标题分块再对超过长度上限的块做滑动窗口补充。切完的每个块要保留来源标记比如来自第2章第3节这样回答引用出处时才有据可依。import re from typing import List def split_markdown_by_heading(text: str, max_chunk_size: int 500): # 按markdown标题切分 sections re.split(r\n(?#{1,3} ), text) chunks [] for sec in sections: if len(sec) max_chunk_size: chunks.append(sec.strip()) else: # 超长的块再按段落切 paragraphs sec.split(\n\n) buffer for para in paragraphs: if len(buffer) len(para) max_chunk_size and buffer: chunks.append(buffer.strip()) buffer para else: buffer \n\n para if buffer.strip(): chunks.append(buffer.strip()) return chunks向量化和检索的代码我会把Embedding模型和向量库封装成独立的模块。这一段的关键点是召回数量top_k和重排序后取多少条rerank_top_n要分开控制。比如向量检索先召回20条重排序后再取前5条进Prompt这样既保证候选覆盖面又不会把上下文撑爆。import chromadb from sentence_transformers import SentenceTransformer class VectorStore: def __init__(self, model_name: str BAAI/bge-small-zh-v1.5): self.encoder SentenceTransformer(model_name) self.client chromadb.PersistentClient(path./chroma_db) self.collection self.client.get_or_create_collection( namedocs, metadata{hnsw:space: cosine} ) def add_documents(self, chunks: List[str], metadatas: List[dict]): embeddings self.encoder.encode(chunks, normalize_embeddingsTrue).tolist() ids [fdoc_{i} for i in range(len(chunks))] self.collection.add(idsids, documentschunks, embeddingsembeddings, metadatasmetadatas) def query(self, question: str, top_k: int 20): emb self.encoder.encode([question], normalize_embeddingsTrue).tolist() res self.collection.query(query_embeddingsemb, n_resultstop_k) return list(zip(res[documents][0], res[metadatas][0]))组装Prompt时我通常用一个模板函数把检索到的片段逐一编好序号塞进去。注意只有重排序之后真正要发给模型的内容才占用最终的上下文窗口。这个意识越早建立越好它决定你的应用能不能处理超长文档。我习惯的做法是检索20条→重排序取5条→每条最多500字那上下文里检索内容部分最多2500字左右给模型输出留足空间。3.4 从能跑到能上线评估这套系统项目跑通之后千万不要说看起来回答得还行就收工。你要建一个最小的评估集准备20~30个问题覆盖简单问答、跨章节组合问答、文档里找不到答案的问题、带攻击性的提示词注入这几类。然后拿一个参考答案的评分模板逐条检查模型的回答是否引用了正确的文档片段、是否如实说不知道。我推荐的做法是把每个测试问题的预期行为写成结构化的检查项比如回答中必须出现文档原文中的指标数字当问题超出文档范围时必须拒绝回答然后用大模型当裁判或者规则脚本去批量判断。这个评估集就是你的安全网。以后不管你换模型、改Prompt、调切块参数都先跑一遍评估集用分数说话而不是感觉变好了。没有评估体系的AI项目就是在裸奔。4. 本地部署AI把学习变成可复现的实践4.1 怎么选本地模型和推理框架很多人在做完知识库助手之后会想把模型也部署到本地彻底摆脱对外部API的依赖。这是很好的进阶练习但一上来就会碰到一道坎显存。我给你的选型原则是显存不够量化来凑参数不在大跑得动才算数。以大众常见的消费级显卡为例做几档参考显卡显存可选模型档位说明8GB7B模型4bit量化日常问答够用速度尚可12GB14B模型4bit量化效果明显更好接近可用24GB32B模型4bit量化综合效果强适合追求质量48GB以上70B模型量化或全精度小模型属于重度玩家数值估算方法也很简单模型显存约占参数量的2倍半精度FP16也就是说一个7B模型半精度大约占14GB4bit量化后约4~6GB再加上KV Cache和中间计算缓冲预留多2~4GB。所以8GB卡跑7B量化版是比较稳妥的组合。推理框架方面我的经验是这样Ollama最推荐入门用。一行命令就能拉起模型服务自带的OpenAI兼容接口让你的代码不用改就能用。llama.cpp适合需要极致控制和部署在CPU机器上的场景。纯CPU跑7B量化模型也能出结果只是慢一些。vLLM适合有一定并发需求的线上服务它对吞吐量的优化很猛但显存占用也相对高配置复杂一点。LM Studio想要GUI图形界面不想敲命令行的话可以用它。本地跑实验、测试模型效果非常顺手。4.2 推理速度和显存的工程级优化本地部署最常见的三个痛点是慢、爆显存、吐着吐着停了。我逐个说解法。慢的解法首要是调整上下文长度。默认的上下文窗口往往拉得很长但你的真实应用可能用不到那么多把num_ctx改小能让显存占用明显下降、速度变快。其次是使用并发请求时小模型用Ollama自带的请求排队就行但如果你用的是vLLM可以用continuous batching连续批处理机制让吞吐量成倍提升。还有一点经常被忽略输入长度越长生成越慢。所以Prompt里只保留必要信息别把一堆没用的检索片段塞进去。爆显存的解法除了量化之外要关注KV Cache。它的大小和你的上下文长度成正比。如果你开一个8K上下文KV Cache可能也要吃好几个GB。一般的处理是在部署配置里限制最大上下文长度给生成留余量。另外模型加载时用gpu_layers参数控制层数在GPU和CPU之间分配别一股脑全塞进去。生成中断的解法最常见的原因是输出超长或触发了上下文窗口上限。我一般会做两层防护第一代码层面设置max_tokens控制单次生成的最大长度第二部署层面设置更保守的上下文上限给Prompt和输出之间留出缓冲。还有一个很隐蔽的问题模型生成的结束符不一定是EOS有的模型会输出一段感谢之类的废话后才停。这时候你在代码里定义一个停止标识列表匹配到就截断能省掉大量时间和token。4.3 本地部署的常见报错速查表我把自己踩过的坑整理成一张速查表遇到同样问题可以直接对号入座报错或现象原因解法CUDA out of memory显存不足换更小量化模型减小上下文长度关闭其他占显存的程序模型加载后首次生成极慢prompt处理阶段在跑长文本缩减检索片段数量启用Flash Attention如果框架支持回答到一半停止触发了上下文上限调大max_tokens或减小上下文长度预留空间CPU模式速度只有几token/s内存带宽瓶颈考虑换GGUF量化等级更低的模型或接受它作为离线预览用途API请求超时本地推理太慢被网关断开调大请求超时时间用流式输出代替一次性等待这里再提醒一句本地部署不要追求一步到位的高难度框架。Ollama真能解决你80%的需求先把服务跑起来后面再慢慢研究vLLM的--quantization参数那些进阶选项。工程这东西跑通是第一优先级优化是后续的事。5. 给新手的实用建议与避坑指南5.1 学习过程中最容易犯的三个错第一个错误是一上来就扎进模型训练和微调。我见过太多人学AI工程第一个月就在看LoRA微调教程结果对Prompt工程和RAG还一知半解。不是说微调没用而是微调解决的是模型能力问题而AI工程日常面对的多是怎么稳定调用模型的问题。你先得学会用模型再去考虑改模型。第二个错误是不重视评估全凭感觉调系统。我早期写RAG每次调完检索参数都觉得好像变好了结果一上线被用户投诉回答变差了。后来老老实实建了评估集才发现直觉根本不靠谱。所有改动的合理性都要靠测试数据来判断。从第一天做项目开始就顺手把测试问题和期望行为记录下来这段积累会在你后面迭代时发挥巨大作用。第三个错误是不愿意看原始输出。调试AI应用时真正的线索藏在模型的完整响应里。很多人在Web界面看到回答正确就以为万事大吉但一旦做流式、做结构化输出模型返回里的那些思考过程“兜底话术才是破坏格式的元凶。我调任何问题第一步永远是打印完整的原始响应JSON从来不看美化后的展示结果。5.2 如果你工作忙怎么保持学习节奏这个方向不是看几篇文章就能掌握的它需要持续的动手时间。我给自己的节奏是小步高频每天至少写半小时代码哪怕只是改一个Prompt、调试一个小函数。不要等周末攒出大块时间再冲刺那样很容易因为一次卡住就放弃。再推荐一个以教代学的办法每完成一个小项目把过程写成一篇简短的经验笔记不需要公开发布就当作是给未来的自己看的操作手册。我现在的很多生产经验其实都是从自己整理的笔记里快速翻出来的。写作的过程会逼你把模糊知道变成确切知道。5.3 最后分享一个我反复用的小技巧不管你是做RAG还是Agent所有发往大模型的请求和所有模型返回的响应都建议留一份带时间戳的日志。手动调试时这个日志目录就是你排查问题最好的朋友——它记录着每一次Prompt的长相、检索到了什么、模型回了什么。比起在终端里翻历史记录看着几十个带时间戳的JSON文件思路会清晰得多。我刚开始做AI工程时也曾经在这模型怎么不听话的抱怨里消耗了大量时间。后来我慢慢意识到问题通常不在模型而在工程链路里某个不起眼的环节——可能是Prompt里少了边界约束可能是检索结果没有排好序也可能是上下文被无关内容塞满了。把每个环节都做成可以观测、可以控制、可以测试的模块你就能真正驾驭模型而不是被模型的随机性牵着走。这条路没有想象中的那么玄它的知识边界很明确方法也是可以复制的。从一个知识库问答助手开始一步步把RAG、评估、本地部署、Agent这些能力叠加上去你会发现自己已经能做出很多以前不敢想的应用。希望这篇梳理清晰的路径笔记能帮你少走一些我走过的那种弯路。