
做AI工程最怕的不是模型不够强而是方向太散。我见过太多人从调一个API开始到写完一个demo就停住再往后就不知道该补什么了。这个“ai-engineering-from-scratch”项目就是我把过去一年从零搭建AI应用踩过的坑、推翻重来的架构、重新设计的提示词全部整理成的一条可复制的路径。它不教你背概念而是从第一个能跑通的模型调用开始一步步做到提示词工程、模型部署、工作流编排、Agent协作和线上排查。适合那些已经会写几行Python、但对“AI工程到底怎么做”还没有完整认知的开发者也适合那些被网上碎片化教程弄晕的入门者。我发现真正的门槛不在模型能力而在工程思维。模型的输出是不确定的链路是容易断的数据是非结构化的这跟传统软件开发完全是两种体验。下面我把这套从零开始的完整思路拆开讲包括每一阶段做什么、为什么这么做、踩坑之后怎么修。1. 项目整体设计与思路拆解1.1 从“跑通接口”到“能上线”之间缺了什么很多人以为AI工程就是调用大模型接口把返回结果放到页面上。真上线过一个项目你就会明白这只是最外面一层皮。一个能跑的AI应用至少要同时解决四个问题提示词怎么设计才稳定、模型怎么选才匹配业务、链路怎么编排才不容易断、效果怎么评估才知道有没有变好。我在做这个项目时第一个版本就是一个聊天机器人直接调用公开接口把用户问题原样丢给模型再把回答原样返回。测试的时候觉得挺聪明上线后发现用户问法一变回答质量立刻崩。后来才意识到模型不变但每次输入都不一样输出自然不稳定。这就像你让一个很专业的同事干活但不告诉他背景、格式、边界和验收标准他每次交回来的东西都长得不一样。所以这个项目的设计思路是反过来的不把精力全花在追新模型上而是先固定一套工程框架把提示词、数据、模型、评估四个环节都变成可维护的模块。模型可以换提示词可以调但框架不能散。1.2 我如何定义这条从零开始的路径我把整条路径分成五个阶段。第一阶段是提示词工程学会用自然语言精确控制模型行为第二阶段是上下文管理理解窗口限制和信息检索的关系第三阶段是模型选型与部署搞清楚什么场景用API、什么场景要私有化第四阶段是工作流与Agent把多个模型调用串成有逻辑的系统第五阶段是效果评估与线上排查让系统在真实流量下保持稳定。每个阶段都对应一个可验收的产物。提示词阶段产出一套可复用的提示词模板上下文阶段产出一个带检索的知识库Demo选型部署阶段产出一个私有化模型服务工作流阶段产出一个多Agent协作的原型评估阶段产出一份带量化指标的测试报告。这样走下来每一步都有东西能拿得出手而不是学了一堆概念却不知道用在哪儿。为什么这么排因为顺序一旦反了学习成本会翻倍。我见过有人先搞私有化部署折腾一周围绕显存和框架的环境问题连模型的输入输出格式都没摸清最后连业务逻辑都没写。先做提示词工程不是因为它最简单而是因为它能最快建立你对模型行为的直觉。有了这份直觉后面做部署和工作流时你才知道哪些问题是模型本身的哪些是工程引入的。1.3 给不同基础读者的路线建议如果你是编程基础薄弱的产品或运营同学可以从提示词工程和Agent工作流开始用可视化平台或低代码框架先跑通逻辑再回头补Python。如果你是有经验的后端工程师建议直接按五个阶段走把重点放在模型部署和链路稳定性上。如果你是搞算法出身反而要刻意补一补工程化那一部分尤其是可观测性和评估体系。这个项目里很多方案并不是唯一解。我尽量在每一次选型时解释背后的理由为什么这个场景用提示词约束而不是微调、为什么这条链路用顺序编排而不是并行、为什么这个指标用人工评估而不是自动化。理解了这些取舍你才算真正进入AI工程的语境。2. 核心细节解析与实操要点2.1 提示词工程的底层逻辑提示词工程听起来很玄本质就一句话在模型的能力范围内用信息组织方式提高它输出的成功率。模型不是理解你的意图它是根据你提供的文字概率分布去生成后续内容。所以你给的信息越完整、越结构化模型越不容易跑偏。我推荐一套标准结构按顺序写下来角色定义、任务目标、输入数据、输出格式、边界条件、示例。这六个部分不是都要写但核心场景建议写全。比如我让模型帮我整理会议纪要提示词写成这样你是一名会议纪要整理助手。 任务把下面的对话整理成结构化的会议纪要。 输出格式 - 议题列表用数字编号 - 每个议题的关键结论一句话 - 待办事项格式负责人|事项|截止时间 边界条件不要补充任何对话中没有提到的内容不要在纪要中加入你的建议。 对话内容如下这么写和直接说“帮我整理一下这段会议记录”的区别很明显。模型知道自己的角色知道按什么格式输出知道哪些事不能做产出就基本稳定在可以用的水平。很多人问我提示词要背多少模板我说不用背掌握这个结构按需拼装就行。2.2 少样本示例才是稳定的关键结构化的任务描述能定方向但真正让输出稳定的是示例。模型跟你一样看一百句抽象描述不如看两个具体例子。我管这叫“给模型打样”。举个例子我想要模型从用户评论里抽取情感倾向并给出原因。那个领域里“无语”有时候是正面比如“好吃到无语”有时候是负面。只靠任务描述根本说不清这种情况但我放两条示例示例1 输入这家店的服务太棒了等位的时候还送了小零食。 输出情感正面原因服务贴心等位时有零食赠送。 示例2 输入等了一个小时结果菜还是凉的真的无语。 输出情感负面原因等候时间长菜品温度不达标。放完这两个例子模型对隐含规则的把握立刻上一个台阶。实际操作中示例数量不用多3到5个就够关键是覆盖边界情况。你把最容易混淆的案例放上去模型就能学会你的判断标准。2.3 上下文窗口不只是一串数字上下文窗口是所有做AI应用的人绕不开的硬约束。很多新手以为窗口大就能把全部资料塞进去这是最大的误解。窗口包含的是这段对话里所有历史消息加你新输入的token总长度。对话一长前面的内容可能被挤掉模型就“失忆”了。我的经验是上下文里只放与当前任务强相关的信息。业务背景、用户历史、知识库文档都通过检索只取最相关的片段拼进去。这就是RAG检索增强生成的核心思路。不要试图让模型记住所有东西而是让它需要什么就能查到什么。做个简单的算术假设模型窗口是128K token你塞进去100K背景资料留给模型思考和输出的空间就只剩28K不仅要承担生成答案还要承担输入问题本身。一旦对话轮数变多老问题就会反复出现。所以上下文管理的关键动作是裁剪和检索而不是充值。内存再大也不能无限塞东西搜索才是解决信息过载的正确姿势。3. 模型选型与部署从API到私有化的完整路径3.1 选模型先看场景而不是参数大小很多人选模型的第一反应是“哪个分高选哪个”这在工程上是个危险的思路。模型不是越强越好而是越匹配越好。我把选型维度拆成四个效果、延迟、成本、可控性。这四个维度往往互相打架。举个例子一个实时客服场景用户发消息后两秒内必须收到回复。这种情况下一个响应速度快的轻量模型哪怕效果稍弱也比一个动辄思考几十秒的大模型更合适。相反一个离线生成营销文案的任务对延迟没要求就可以用效果更强的模型哪怕成本高一点也值得。我还会看模型的生态兼容性。同一个模型在不同推理框架下的表现可能有差异工具链是否完善直接决定你能不能顺利调用、便捷地做量化或批处理。选型时我固定会做一个小测试拿自己业务里最典型的20条输入分别让候选模型跑一遍人工打分。这个过程叫“效果基线测试”虽然简单但比任何排行榜都贴近真实需求。3.2 私有化部署一套开源模型的完整流程当业务有数据合规要求或者API调用成本高到难以接受时私有化部署就成了刚需。这个项目里我完整走了一遍流程这里给出一个可以直接参考的路径。我选的是Qwen系列的开源模型因为它中文效果稳定、生态成熟、量化方案也多。第一步准备推理环境。我的机器是单张24G显存的显卡这个级别的显存跑7B到14B的量化模型刚刚好。先装好Python虚拟环境然后安装transformers、accelerate、sentencepiece这几个核心依赖。第二步下载模型权重用Hugging Face的镜像站直接拉取官方权重。第三步用vLLM起服务因为它批处理能力强并发响应性能比原生transformers高很多。# 安装依赖 pip install transformers accelerate sentencepiece vllm # 启动模型服务以Qwen2.5-7B-Instruct为例 python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --gpu-memory-utilization 0.9 \ --max-model-len 8192 \ --port 8000启动之后你会得到一个兼容OpenAI接口格式的本地服务。这意味着你原来写的调用代码几乎不用改只要把base_url换成http://localhost:8000/v1就行。这一步对工程迁移非常友好不需要重写业务逻辑。3.3 量化与并发部署环节的必修课私有化部署最常见的问题就是显存不够。我强烈建议上手先做量化。4比特量化能把模型体积压缩到原来的四分之一左右7B模型量化后大约4到5GB跑起来非常流畅效果损失在大多数任务上可以接受。关于并发vLLM的连续批处理机制能把多个请求动态拼成一个批次显存利用率高很多。但并发数不是越大越好我实测下来24G显存上7B模型并发调到8到16之间比较安全再往上就会触发显存溢出。另一个容易忽略的点是max-model-len设置。这个参数控制单次请求的最大长度设得越大能同时跑的请求数越少。业务场景如果多数是短对话就没必要设成8192设4096能显著提升并发能力。部署完成后一定要做一次压测。我习惯用wrk或简单脚本并发请求观察响应时间和错误率变化。这一步能帮你提前发现显存不足和队列堆积的问题而不是等用户来投诉。4. 工作流与Agent把单点能力串成有逻辑的系统4.1 单次调用与工作流的边界单一模型的直接调用能解决“一问一答”型任务但现实中很多需求是多步骤的。比如“分析用户投诉并生成处理建议”完整流程是先做意图识别再抽取关键实体再查历史工单最后生成建议。每一步用不同的模型或不同的提示词串在一起才是一个合格的AI应用。我划分工作流边界的标准是如果一次调用需要分成多个子任务并且每个子任务的结果会影响下一步的逻辑分支那就必须引入工作流。工作流工程的价值在于把不确定性拆成多个可控制的节点。每个节点做一件简单的事要么成功要么失败可重试可单独调试。相比之下一个大而全的提示词像一锅乱炖出了问题你都不知道是哪个配料坏了。4.2 一个多Agent协作的小案例多Agent协作通常是工作流的升级形态核心思想是让多个专职的“角色”分工配合。这个项目里我搭了一个内容创作Agent小组由三个角色组成选题Agent负责根据热点收集素材并产出观点写作Agent负责把观点扩展成完整文章审校Agent负责检查事实性错误和表达问题。三个Agent之间通过消息队列传递任务。选题Agent完成后把“选题卡片”发给写作Agent写作Agent完成后把草稿发给审校Agent。关键设计是每个Agent都有独立的提示词和输出格式约束互不干扰。比如审校Agent的提示词里明确要求“只输出问题清单不重写文章”这样它就不会越权改动内容。# 简单的Agent调用示意 def run_content_pipeline(topic: str) - dict: idea topic_agent.run(topic) # 产出选题卡片 draft writing_agent.run(idea) # 产出文章草稿 review review_agent.run(draft) # 产出问题清单 if review.issues: draft writing_agent.run(draft, review.issues) # 按问题修订 return {draft: draft, review: review}这里有个工程细节不要让Agent在同一个上下文里反复对话而是用结构化数据传递中间结果。这样每个Agent的输入输出都是稳定可解析的JSON流程可以被追踪出错时也能定位到具体环节。4.3 工程化关键可观测性和重试机制Agent多了之后最怕的是链路悄悄失败。写代码的时候模型不可用的报错会直接抛出来但在Agent工作流里模型“成功返回了一段废话”这个情况更难察觉。所以我给每个环节加了三个东西输入输出日志、耗时与token消耗统计、状态标记。日志记录每一轮的输入长度、输出长度、延迟和使用的模型版本。token消耗直接和成本挂钩这个必须量化。状态标记则区分四种情况成功、失败、部分成功、需要人工介入。部分成功是我最关心的一个状态比如审校Agent发现三条问题其中一条无法确认这时候就把它标记为需要人工检查而不是让流程强行继续。重试机制也不能是无脑重试。模型接口的错误分两种一种是限流或超时重试有意义另一种是内容审核拦截或输出格式不对重试十遍结果都一样。我的做法是设置分层重试网络类错误重试三次间隔递增业务类错误直接跳到人工兜底逻辑。这个兜底逻辑可以是模板回复也可以是降级到另一个更小的模型总之不能把错误直接暴露给用户。5. 常见问题与排查技巧实录5.1 最常踩的五个坑第一个坑是忽略输入输出的格式校验。模型是概率生成的你告诉它输出JSON它偶尔会在JSON前后多一行解释文字直接json.loads就会报错。解决方式是抽取返回结果里的代码块再解析同时写一个宽松的正则兜底。第二个坑是上线后才发现模型被“越狱”。用户可能会把一串精心构造的指令塞进输入诱导模型说出不该说的话。因此无论什么场景都必须加一层输入安全过滤和输出审核。第三个坑是上下文越塞越多导致成本和延迟同步上涨。有个阶段我的调用量没增加但账单涨了排查后发现是有个历史记录功能把所有旧对话都拼进请求了。第四坑是忽略模型版本升级带来的输出变化。同一个提示词换成新版本模型输出风格可能明显改变。这要求你对线上模型版本做固定快照不要跟随最新版自动升级。第五个坑是不做效果回归测试改了一版提示词后整体效果提升了但某个旧场景反而变差了。没有回归用例这种退化很难被发现。5.2 排查工具箱从日志到链路追踪遇到问题我第一件事永远是看日志而不是重新读代码。我给每条请求分配一个request_id从入口到每一个模型调用都带上它这样就能把一次用户的完整链路串起来。日志里包含模型名、输入长度、输出长度、耗时、状态码。有了这些多数问题都能定位到具体环节。再进一步我会用监控看板统计三类指标成功率、平均延迟、token消耗趋势。成功率掉下来的时候优先查是不是模型服务过载延迟变高的时候优先查上下文是不是变长了token消耗异常上涨的时候优先查是不是有循环调用或重试过多。如果问题只在个别用户身上出现就把那个用户的完整上下文导出来复跑。我用这个办法定位过一个特别隐蔽的问题某个用户的历史对话特别长超过了窗口限制导致模型回复质量下降但当时日志里并没有报错因为调用本身是成功的。发现这类问题靠日志还不够必须同时监控输入长度分布提前发现靠近窗口上限的请求。5.3 几个亲测有效的避坑技巧关于提示词的迭代我强烈建议每次只改一个变量。很多人一次改了角色描述、输出格式和示例效果变好了但不知道具体是哪个改动起的作用下次复现不了。我做了一个简单模板版本管理提示词存成文本文件带版本号实验时跑同一批测试用例对比。稳定之后再改下一个变量。关于小模型和大模型的分工我习惯把简单任务交给轻量模型复杂任务留给大模型。意图识别、实体抽取、标题生成这类标准化任务轻量模型足够需要创意、推理或长文生成的才上调大模型。这样成本能省一大截效果还不降。关于上线前的检查清单我的固定动作是跑一遍全链路冒烟测试、检查输出格式解析率是否达到100%、验证未知输入的兜底逻辑、确认日志和监控已经接入。这套检查做完再上线出问题的概率会小很多。这个项目做到后期我最大的体会是AI工程的重点已经从“让模型更聪明”慢慢转向“让系统更可靠”。模型能力会不断进步大家都会用的时候拼的就是谁的工作流更稳、评估更准、排查更快。从零开始不是把流程从头学一遍而是从一开始就把这些习惯刻进代码里。哪怕你的第一个项目只是一个简单的问答机器人也值得按这套工程标准去做因为你迟早会用得上。