最近大半年我给自己定了一个略带“自虐”的技术课题ai-engineering-from-scratch。简单说就是不依赖任何现成的AI黑盒平台从模型选择、环境搭建、数据准备到应用落地把AI工程的完整链路亲手走一遍。做完以后最大的感受是AI工程不是某个单一技能而是一整套把大模型变成可用产品的系统工程。这篇文章适合那些已经能用Python写脚本、但对AI工程还停留在“调接口”阶段的开发者也适合想系统梳理自己知识体系的同学。如果你跟我一样对数不清的AI框架、Agent概念、提示词技巧感到眼花缭乱那这篇文章应该能帮你把线索理清楚。我不会只讲概念而是会结合我自己从零搭建项目时踩过的坑、试过的工具、反复重写的代码尽量说人话给可复现的路径。毕竟真正把一个大模型跑进自己的工程里和看十篇教程完全是两码事。1. AI工程到底在解决什么问题1.1 你以为的AI开发和实际的AI工程差在哪很多新手入门的路径是装一个Python环境pip install openai然后把API调通写一个“给我讲个笑话”的交互Demo。这一步确实很爽但它是“AI应用”而不是“AI工程”。工程意味着你需要考虑输入不可控怎么办、模型幻觉怎么处理、用户并发一上来会不会挂、同一个Prompt在不同模型上表现差多少、怎么监控线上效果。好比做菜和开餐厅的区别做菜只需要把菜炒熟开餐厅要管的却是供应链、后厨动线、出菜速度、顾客投诉和食品安全。AI工程就是那间餐厅模型只是你后厨里最贵的一口锅。从我自己的经验看AI工程要解决的问题基本可以拆成五块模型怎么选、数据怎么处理、应用逻辑怎么写、效果怎么评估、系统怎么部署和迭代。这五块环环相扣。很多人只盯着“模型怎么选”和“提示词怎么写”结果上线后发现数据格式脏乱差导致召回效果崩盘或者模型输出没有校验导致下游程序直接报错。工程思维的关键是你关注的不再是“某一次输出好不好”而是“一百次请求里有多少次是好结果那些坏结果怎么兜底”。1.2 为什么一定要从零开始走一遍有人会问现在那么多现成平台拖拽一下就能建一个对话机器人何必自己造轮子我的看法是用现成平台做业务验证是高效的但如果想把AI能力变成自己的核心竞争力必须亲手构建关键环节否则出了问题只能干瞪眼。我见过不少团队用某平台搭出来的客服机器人效果不好想调优结果只能等平台更新自己完全没有介入空间。这种黑盒依赖在生产环境里是非常危险的一件事。从零开始走一遍至少有三个具体收益。第一你能真正理解Token成本、上下文窗口、Embedding这些概念在系统里的作用而不是停留在名词层面。第二你会被迫做工程化决策比如该用SQLite还是向量库存知识该用流式输出还是整体返回。第三你会积累一套自己可控的调试手段。我自己做完一遍以后再去评估各种框架和平台基本一眼就能看出它们的抽象层次在哪里、哪些功能是真正的价值哪些只是包装。2. 从零起步需要啃下的四块硬骨头2.1 语言与工具基础Python是入场券但不是全部AI工程的主流语言还是Python不是说别的语言不行而是模型生态、数据处理库、部署样例大部分都优先支持Python。所以如果你的Python还停留在“能写循环和函数”的阶段建议先把这几样补齐虚拟环境管理venv或conda、依赖管理requirements.txt或poetry、文件读写和异常处理、基础的数据处理用pandas处理表格用json处理接口返回。这些基础花不了太久但缺了它们你在AI项目里会非常难受。除了PythonGit是必须的。我刚开始做AI项目时不习惯频繁提交结果有一次改坏了一个Embedding配置花了一个下午都没还原干净最后只能靠记忆重写。那次之后我养成了习惯每个可运行的状态都打一个tag。另外Linux基础命令也要够用因为本地部署模型、跑批处理、看服务日志基本都是Linux环境。如果你平时在Windows下开发至少学会用WSL2很多AI依赖包在Linux下安装会少掉一半坑。2.2 大模型核心概念不止是“聊天”那么简单到了AI工程你需要深挖的概念并不是Transformer结构里的注意力公式而是那些直接影响工程决策的东西。第一个是Token。Token是模型计费、上下文长度计量的基础中文里一个汉字通常占1到2个Token英文一个单词可能拆成几个子词。你设计Prompt时如果动辄塞进去几千字多轮对话时很容易把上下文窗口塞爆所以必须学会做裁剪和摘要。第二个是上下文窗口和温度参数。上下文窗口决定模型能记住多少信息温度决定输出的随机性。做客服机器人和做代码生成温度设置肯定不一样。第三个是提示工程也就是Prompt Engineering。很多人在这个点上用力过猛追求花哨的few-shot模板但我后来发现最简单有效的提示工程是先交代角色、再给出背景、然后说清楚输出格式最后给一两个例子。最后是函数调用和结构化输出这是把模型接入工程系统最重要的能力。别只让模型输出自然语言要让模型输出JSON你的程序才好解析和校验。这一块值得花时间练基本上AI工程里一半的调试时间都耗在这里。2.3 本地部署把模型真正攥在自己手里我选的第一条路是做本地部署。原因是如果只依赖云端API很多需要隐私数据处理的场景根本没法落地而且API调用一多成本就很容易失控。本地部署的起步工具我在2024年到2025年之间反复对比过几个最推荐新手的是Ollama。它把所有复杂的模型加载、推理优化都打包成了简单的命令行操作你可以像装普通软件一样把Qwen、DeepSeek、Llama这些开源模型拉到自己的机器上跑。当然本地部署不意味着万事大吉。你马上会遇到两个现实问题显存和速度。我自己的机器是一张12GB显存的显卡跑7B左右的量化模型还能流畅对话跑到14B模型就会明显变慢如果开的并发一多基本卡死。所以我最终的方案是本地部署小模型做数据处理和草稿生成大模型需求走云端API两套并存。这个混合策略是很多中小项目的通用做法。2.4 Agent与工作流从“一问一答”到“自己干活”把AI工程和普通接口开发区分开的还有一个重要概念AI Agent。简单理解Agent是让模型不只是回答你而是自己判断下一步该调用什么工具、查什么数据库、写什么代码。最经典的框架是ReAct也就是模型根据当前信息思考下一步行动然后观察结果再继续思考直到完成目标。从工程角度我不建议一上来就上LangChain那套复杂编排而是先自己手写一个极简的Agent循环把模型输出解析成“思考动作参数”然后你的代码根据动作去调用工具把结果拼回去再交给模型。这个过程走一遍你对什么是有状态、什么是工具调用会理解得非常透彻。我后来看了LangChain的源码发现核心也就是这个循环只是封装了很多细节。亲手做过之后再去看那些封装才会觉得它们只是省事而不是魔法。3. 工具链选型与实践我最终留下的组合3.1 模型层本地开源模型与云端API怎么取舍模型选择可能是最让人眼花缭乱的一步。我的原则是先用云端API验证效果再用本地模型做成本优化。最开始我直接用了各家的云端大模型API效果确实稳但跑几天测试就烧掉了不少额度。后来我换了本地模型效果在某些场景会打折扣但胜在省钱且不限制调用频次。在开源模型里我个人比较常用的是阿里系的Qwen系列和DeepSeek系列。Qwen的中文理解扎实指令跟随也做得不错非常适合中文知识库问答场景。DeepSeek在代码和数学推理上更有优势。选型时还要注意模型参数量的变化7B模型可以追求速度14B模型可以追求效果但你需要根据机器性能做权衡。我最终固定下来的组合是本地跑一个7B量的模型处理大量重复任务遇到复杂问题再调用云端高能力模型。这样成本能压到很低的水平又不牺牲核心体验。3.2 编排层LangChain、LlamaIndex还是自己写框架的选择代表着你愿意在哪一层做抽象。LlamaIndex对文档检索和知识库场景做了大量优化适合做RAG。LangChain则是一个通用的Agent和工具编排框架功能很全但版本更新快接口变动也频繁。我自己试下来深度使用LangChain需要付出不少学习成本而且出了问题很难定位。相比之下LlamaIndex在RAG场景里更顺手索引、检索、拼接上下文的逻辑很清晰。不过到了真正要上线的项目我反而选择了自己写轻量编排。原因很简单框架封装太多调试复杂而且并发热点、日志、重试这些逻辑最终还是要自己控制。我的建议是框架可以拿来学习但核心业务链路自己写。你可以参考LlamaIndex的检索逻辑也可以偷学LangChain的工具调用机制但最后的执行代码一定要在自己手里这样出问题的时候才能半小时内定位到具体行。3.3 提效辅助AI编程插件、向量库与部署工具聊完模型和框架再来说说辅助工具。我这段时间几乎把AI编程插件用成了肌肉记忆。它帮我写正则、补测试用例、解释报错原因节省了特别多精力。但有一点要注意AI生成的代码必须做Code Review尤其涉及第三方依赖调用的部分经常会自己发挥版本号或过时API。我用AI编程插件生成过一段时间处理代码它写的是Python里没有的方法编译才报错这种坑很典型。向量库也是AI工程标配。如果你想做一个知识库问答肯定要把文档切成片段用Embedding模型转成向量再存起来。向量库的选择上小项目从Chroma或FAISS起步就够了数据量达到百万级再考虑Milvus或Qdrant。我实际用过ChromaAPI设计非常简单适合做原型验证。最后部署工具我推荐Docker加GitHub Actions。Docker保证本地和线上环境一致GitHub Actions可以自动跑测试和部署这两样配合起来AI服务的迭代周期能大幅度缩短。4. 实操从0到1做一个本地知识库问答应用4.1 需求定义与技术选型为了把前面的概念落成代码我拿“公司内部制度问答”做一个最小项目。需求很简单输入一个员工的自然语言问题系统从一堆制度文档里找到相关段落再让大模型生成准确回答。说白了就是一个RAG应用。我的技术选型如下本地部署Qwen 7B作为生成模型搭配一个Embedding模型用于文本向量化向量库用Chroma整个服务用FastAPI写一个HTTP接口。之所以不用云端API是因为制度文档有保密要求必须本地处理。这个场景非常典型你也可以换成产品说明书问答、个人笔记助手或者法律条文咨询。选型时一定要先把“数据能不能出内网”这个问题想清楚否则架构做完了才发现合规过不去会非常被动。4.2 搭建环境与核心代码实现环境搭建其实比想象中简单。先装Ollama拉取模型ollama pull qwen2.5:7b-instruct再拉一个Embedding模型像bge-m3。向量库我用Chroma的Python包一条pip命令就能装。构建流程分四步文档加载、切分、生成向量、存入向量库。切分这一步我踩过坑最开始按固定字符数切结果一句话被切成了两半检索时语义就残缺了。后来我改成按段落加重叠窗口切效果立刻好了很多。核心检索逻辑大致是把用户问题用同一个Embedding模型转成向量然后在Chroma里做相似度检索取前三四名文档片段把它们拼成上下文再交给大模型生成。这个流程用代码写出来其实不超过一百行。关键部分我贴一个简化的伪代码感受一下from chromadb import Client from sentence_transformers import SentenceTransformer client Client() collection client.get_or_create_collection(rules) docs load_and_split(rules/) embedder SentenceTransformer(BAAI/bge-m3) vectors embedder.encode(docs) for i, vec in enumerate(vectors): collection.add([str(i)], [vec], documents[docs[i]]) question 年假可以累计到下一年吗 qvec embedder.encode([question]) hits collection.query(query_embeddingsqvec, n_results3) context \\n.join(hits[documents][0]) prompt f请根据以下制度摘录回答问题\\n{context}\\n问题{question}这里有一个很容易忽略的细节Embedding模型必须和检索阶段的模型保持一致不能文档用A模型转查询时用B模型转否则向量空间不对齐检索结果基本靠猜。我自己就曾经因为换了Embedding模型后忘了重新生成索引导致检索准确率暴跌。4.3 流式输出、日志与接口封装知识库问答如果只是离线测试那还没到工程化。工程化至少要解决三件事流式输出、请求日志、接口错误处理。流式输出可以让用户看到逐字生成的效果体感上比等一大段一次性返回要好很多。FastAPI里可以用StreamingResponse把本地模型的输出逐token推到前端。这部分的背压和取消逻辑也比较麻烦但值得做。日志是最容易被忽略的。我会把每次请求的问题、检索到的文档ID、生成的答案、响应耗时全部记录下来。这样当用户反馈“答案不对”的时候你能快速判断问题出在检索环节还是生成环节。我见过太多项目上线后完全靠用户截图反馈排查效率极低。加上日志后你可以定位到某一次请求到底召回的是哪些文档是不是把无关内容拼进去了从而针对性优化切分逻辑或重排序策略。接口错误处理也很关键。大模型输出偶尔会不合法比如它可能输出某些特殊符号导致JSON解析失败。所以我在接口层做了一个统一的异常捕获把解析失败、超时、模型不可用全部转成固定结构的错误码返回前端看到错误码再给用户一个友好的提示而不是暴露一堆堆栈信息。这些细节才是AI工程里真正体现“工程”二字的环节。5. 工程化进阶评估、优化与交付5.1 评估体系不能只看“感觉变聪明了”做AI应用最怕的是“拍脑袋优化”。你今天把切分长度从300改成500问了两三个问题感觉好像更准了就决定上线。但第二天用户换了一批问法效果又崩了。真正可靠的评估方式是建立测试集。把你希望系统做对的100个问题写下来每个问题配标准答案或关键要点然后每次改动之后跑一遍这100个问题看准确率变化。评估标准不只有“答案对不对”这一项。我还加了三个指标检索召回率、答案相关性和响应耗时。检索召回率可以看出文档切分和Embedding选型合不合理答案相关性要人工评分或者用另一个模型做打分响应耗时决定了用户体验的底线。在本地跑7B模型时如果超过10秒还没出结果用户就会觉得卡。这时候就要考虑换小模型、加缓存或优化切分逻辑。5.2 性能优化与成本控制性能优化要分场景。如果你的服务是低并发、长文档的问答瓶颈多半在生成模型上。你可以用流式输出先发一个“正在思考”反馈再把答案慢慢吐出来。如果你的服务是高并发的短请求比如文本分类瓶颈可能在Embedding和向量检索上。这时候要加一层缓存把相同或相近的查询结果缓存住减少重复计算。成本控制方面我的核心经验是“能不开API就不开API”。能复用本地模型的任务绝不动云端高能力模型。比如先让本地小模型判断问题属于什么类型只有少数复杂问题才转发到云端。还有在上下文拼接时要认真检查有没有塞入重复或无关的文档片段因为上下文越长Token成本越高而且垃圾进垃圾出。我后来写了一个上下文预算器每次拼Prompt前估算Token数超出预算就先摘要历史。5.3 从Demo到可用服务的最后一公里Demo和可用服务之间的差距往往不在代码而在周边配套。你需要为系统写清晰的README让别人能在10分钟内跑起来你需要做模型版本管理换模型时能一键回滚你需要把依赖打包成Docker镜像确保换个机器不会因为环境不同而崩溃。我自己的项目有一次因为升级了Python依赖包隐式地把一个底层库换掉结果向量检索结果莫名少了某些记录花了整整一天才排查出来。自此以后我建立了一个原则每次只升级一个依赖并且在升级后跑一遍全部测试集。最后还有一个容易被忽略的点要给系统留“人工兜底”的出口。AI模型即使做到95%准确也会有5%的错误这在知识库场景里可能会导致用户投诉或者业务事故。所以在你的应用里提供“转人工”按钮或者让管理员能看到错误案例并手动纠正是很有必要的。这不是示弱而是负责任地把AI放在真实环境里。6. 常见问题与排查技巧实录6.1 本地部署后模型输出中文乱码或生成不完整这个问题我遇到过好几次通常不是模型出了问题而是环境编码或上下文长度设置不对。Windows下要确保代码文件保存为UTF-8启动服务时也要声明字符编码。生成不完整多半是max_tokens设置太短本地模型默认可能只有256或者512长回答后半段直接被截断。检查方式很简单把生成参数打印到日志里看是不是max_tokens太小。我一般做问答时会设置成1024甚至2048视情况调整。6.2 向量检索结果明显不对相关性差检索效果差先别急着换模型。按顺序排查第一文档切分是否合理有没有把语义完整段落切掉第二查询和文档是否用了同一个Embedding模型第三用户问题的表述和文档里的表述差异太大比如文档里写“年假”用户问“带薪休假”这时候需要加同义词扩充或引入查询改写。我建议在检索代码里先把检索到的文档片段打出来看看如果问题出在召回再继续往下排查。6.3 构建内容安全自查清单在我个人的实操总结中这里要给所有做AI内容生成场景的朋友提个醒在工程链路里加入“内容安全输出过滤”这层是必要的。不是说模型本身有问题而是生成式系统天然存在输出不可控的概率所以要在系统入口和出口做审核。入口负责识别用户输入是否涉及违规内容出口负责过滤模型输出中的敏感信息或者不合法表达。实现上可以先用规则库做第一道拦截再让模型对模型输出内容进行自检。这样看起来多了两步却能避免很多不必要的麻烦这也是AI工程里负责的体现。6.4 常见问题速查表问题现象常见原因排查建议模型回答胡编乱造上下文没有提供足够背景检查检索召回的相关文档是否真正包含答案同一问题结果不稳定温度参数过高把temperature降到0.2以下API调用报超时并发请求太多或网络波动加超时重试限制并发数生成内容涉及违规输入输入过滤缺失在入口加规则校验和内容审核接口文档切分后语义不连贯切分粒度过细按段落切分增加重叠片段这些坑都是我自己一笔一笔踩出来的。尤其是最后一张速查表我希望你在遇到问题时先对照一遍很多时候能省下好几个小时的无效排查。我自己的体会是AI工程没有捷径但有一条清晰的爬坡路径先把模型调通再搭出完整链路再建立评估体系然后不停地拆掉重做。你不需要一开始就掌握所有框架也不需要把所有模型都跑一遍但你一定要亲手写完一个最小闭环然后反复问自己如果这里的模型输出不理想我该怎么定位问题如果并发量冲到十倍系统会不会崩如果把某个组件换掉评估数据能不能告诉我新组件到底是变好还是变坏这些问题的答案只能在一次次真实项目里长出来。希望我这一个阶段的记录能帮你少走几段弯路。