
1. 从零搭建AI工程能力为什么我劝你别一上来就调包这两年AI应用开发的门槛肉眼可见地降低了一个刚入门的开发者装好环境、拿到API Key半天时间就能跑出一个能对话的Demo。但我带过不少新人也看过很多团队的项目发现一个很普遍的现象Demo跑得飞快一旦要上线、要迭代、要处理真实业务数据问题就全冒出来了。模型输出不稳定、成本失控、响应慢、幻觉频发、评测没有标准、改一个Prompt结果另一条链路崩了——这些都不是“调个包”能解决的它们属于AI工程的范畴。“ai-engineering-from-scratch”这个标题我理解的核心不是“从零训练一个大模型”那既不现实也没必要。它真正指向的是从零构建一套能支撑AI应用稳定运行的工程体系。这包括数据管线的搭建、Prompt与上下文的管理、模型调用层的抽象、评测与回归机制、成本与延迟的监控、以及上线后的可观测性。说白了就是让AI应用从“能跑”变成“能扛”。这套东西适合谁如果你是把AI当玩具玩玩的爱好者可能觉得这些太重了但如果你是要把AI能力真正落到产品里、要对结果负责的开发者或技术负责人那这些工程能力就是绕不过去的坎。我自己踩过的坑告诉我越早建立这套体系后面越省心。下面我就按自己实际搭建的顺序把每个环节拆开讲清楚包括为什么这么设计、具体怎么做、以及我踩过的那些坑。2. 整体架构设计先想清楚分层再动手写代码2.1 为什么不能把所有逻辑塞进一个函数我见过最典型的“反面教材”是一个几百行的Python脚本读用户输入、拼Prompt、调模型、解析结果、写数据库全在一个函数里。刚开始跑得挺欢等到要换模型、要加缓存、要做A/B测试的时候改一处就牵一发而动全身。这就是没有分层的代价。从零搭建AI工程第一件事是分层。我的经验是至少分成四层接入层、编排层、模型层、数据与观测层。接入层负责接收请求、鉴权、限流编排层负责Prompt组装、上下文管理、工具调用、结果解析模型层负责统一封装不同厂商的模型调用数据与观测层负责日志、指标、评测数据的沉淀。这样分层之后换模型只动模型层改业务逻辑只动编排层互不干扰。提示分层不是为了“看起来专业”而是为了在需求变化时把改动范围控制到最小。这一点在AI应用里尤其重要因为模型和Prompt的迭代频率远高于传统后端。2.2 技术选型背后的取舍逻辑选型这块我不推荐盲目追新。语言上Python生态最成熟LangChain、LlamaIndex这类编排框架、各种评测库都齐全适合快速起步但如果你的主业务是Java或Go也没必要为了AI单独切语言用HTTP把AI服务独立出来即可。我的做法是AI能力做成独立的服务通过标准接口对外暴露主业务用什么语言都不影响。编排框架要不要用我的建议是初期可以用但一定要理解它帮你做了什么。LangChain这类框架封装了大量细节上手快但出问题时排查成本高而且版本迭代快、破坏性变更多。我自己的做法是核心链路尽量用原生SDK手写框架只用来做原型验证。这样虽然前期多写点代码但可控性强得多。存储方面向量库选型要看数据规模。几万条以内用FAISS这种本地库就够了上百万条再考虑Milvus、Qdrant这类专业向量数据库。别一上来就上重型方案运维成本会吃掉你大量精力。2.3 目录结构长什么样一个清晰的目录结构能省掉很多沟通成本。我常用的结构大致是这样ai-service/ api/ # 接入层路由、鉴权、限流 orchestration/ # 编排层prompt、上下文、工具调用 models/ # 模型层各厂商客户端封装 evaluation/ # 评测数据集、指标、回归脚本 observability/ # 观测日志、指标、追踪 configs/ # 配置模型参数、prompt模板 tests/ # 测试这个结构的好处是任何人拿到项目一眼就能知道去哪找什么。尤其是evaluation和observability这两个目录很多项目一开始没有等到出问题才补结果发现历史数据全丢了非常被动。3. 核心模块拆解每个环节的关键细节3.1 模型调用层统一封装是刚需模型调用层最核心的价值是屏蔽差异。不同厂商的API在参数命名、返回结构、错误码、流式输出格式上都不一样。如果业务代码直接调各家SDK换模型时就是灾难。我的做法是定义一个统一的接口比如generate(messages, **kwargs)内部再适配各家。这里有个细节值得说重试与超时策略。模型调用失败是常态网络抖动、限流、服务端偶发错误都会导致失败。我一般设置指数退避重试最多3次超时按模型类型区分——对话类给30秒长文本生成给120秒。但要注意不是所有错误都该重试比如参数错误、内容审核拦截重试多少次都没用反而浪费配额。所以错误分类很重要。def call_with_retry(fn, max_retries3, base_delay1.0): for attempt in range(max_retries): try: return fn() except RetryableError as e: if attempt max_retries - 1: raise time.sleep(base_delay * (2 ** attempt)) except FatalError: raise另一个容易被忽略的点是Token计数。很多厂商的返回里带usage字段但流式输出时往往拿不到。我的做法是在调用前用tokenizer预估调用后再用实际值校正两者都记录下来用于成本核算。3.2 Prompt与上下文管理别把Prompt写死在代码里Prompt写死在代码里是我见过最常见的坏习惯。一旦要调整就得改代码、走发布流程效率极低。正确做法是Prompt模板化、配置化放在独立的配置文件或配置中心里支持热更新。模板化还有个好处是版本管理。每次Prompt变更都应该有版本号配合评测数据能清楚知道这次改动是变好了还是变差了。我一般用类似prompt_v3_20240501这样的命名配合Git管理回滚非常方便。上下文管理是另一个重灾区。多轮对话时历史消息无限增长Token很快爆掉。常见策略有几种滑动窗口只保留最近N轮、摘要压缩把早期对话总结成一段话、关键信息抽取只保留实体和意图。我的经验是摘要压缩关键信息抽取组合使用效果最好既保留了长期记忆又控制了Token量。但摘要本身也要调模型有额外成本所以要权衡。注意上下文裁剪一定要保留系统Prompt和最近一轮用户输入这两部分丢了模型基本就“失忆”了。3.3 评测体系没有评测就没有迭代这是我认为从零搭建AI工程里最重要、也最容易被跳过的一环。很多人改Prompt、换模型全凭“感觉好像好了一点”这是非常危险的。没有量化评测你根本不知道改动是优化还是劣化。评测体系至少包含三部分评测数据集、评测指标、回归流程。数据集要覆盖典型场景和边界情况我一般会攒几百条真实业务问题人工标注期望输出或评分标准。指标方面分类任务看准确率、召回率生成任务可以用BLEU、ROUGE这类自动指标但更靠谱的是用模型评模型LLM-as-Judge让一个强模型给输出打分配合人工抽检校准。回归流程是关键每次Prompt或模型变更自动跑一遍评测集对比新旧版本的指标。如果指标下降超过阈值就阻断发布。这套流程搭起来要花点时间但一旦跑通迭代效率会提升一个量级。评测维度常用方法适用场景准确性人工标注准确率分类、抽取相关性LLM评分问答、对话安全性规则模型审核所有生成场景一致性多次采样对比需要稳定输出的场景延迟端到端计时所有线上场景3.4 可观测性上线只是开始AI应用上线后最怕的就是“黑盒”——用户反馈不好但你不知道是哪一步出了问题。可观测性要解决的就是这个。我一般记录三类数据请求日志输入、输出、模型、参数、耗时、指标QPS、延迟分布、错误率、Token消耗、追踪一次请求经过哪些环节每步耗时多少。日志里有个细节用户输入和模型输出要脱敏。真实业务数据里可能有手机号、身份证号直接落库有合规风险。我一般用正则做基础脱敏敏感场景再加一层专门的脱敏服务。指标监控要设告警。比如错误率超过5%、P99延迟超过阈值、单日Token消耗超过预算都要及时通知。我踩过的坑是有次模型厂商悄悄调整了默认参数导致输出变短、质量下降但因为没监控输出长度分布过了好几天才发现。从那以后我把输出长度、拒绝率、异常格式率都加进了监控。4. 实操落地从零到跑通的完整流程4.1 环境准备与依赖管理第一步是把环境搭起来。Python项目我强烈建议用uv或poetry做依赖管理别用裸pip。原因很简单AI项目依赖多、版本冲突频繁没有锁文件换台机器就装不起来。uv速度快poetry生态成熟选哪个都行。# 用uv初始化项目 uv init ai-service cd ai-service uv add openai faiss-cpu pydantic fastapi配置文件用.env管理密钥但千万别把.env提交到Git。我一般提供.env.example里面写清楚需要哪些变量新人照着填就行。密钥读取统一走一个config模块方便后续换成密钥管理服务。4.2 最小可用链路先跑通再优化别一上来就追求完美架构。我的做法是先搭一条最小可用链路接收请求→组装Prompt→调模型→返回结果。这条链路跑通后再逐步加缓存、加重试、加评测。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class Query(BaseModel): text: str app.post(/generate) def generate(q: Query): prompt build_prompt(q.text) result model_client.generate(prompt) return {result: result}这条链路虽然简单但已经能验证核心流程。接下来每加一个能力都确保它不破坏已有功能这就是工程化的思路。4.3 参数调优温度、Top-p到底怎么设模型参数不是随便填的。温度temperature控制随机性0接近确定性输出1以上发散。做事实问答、数据抽取温度设0到0.3做创意写作可以设0.7到1.0。Top-p是另一种采样策略一般和温度二选一调不要同时大改。我一般会针对每个场景做小规模实验固定其他参数只调一个看评测指标变化。比如抽取任务温度从0.7降到0.2准确率可能提升十几个点。这些都要靠评测数据说话不能拍脑袋。提示有些模型对参数不敏感有些非常敏感。换模型后原来的参数不一定适用一定要重新跑评测。4.4 成本控制别让账单吓到你Token成本是AI应用绕不开的话题。控制成本有几个实用手段缓存相同或相似请求直接返回缓存结果、模型分级简单任务用小模型复杂任务用大模型、Prompt精简去掉冗余示例和说明、输出长度限制设置max_tokens。缓存这块要注意语义缓存比精确匹配缓存命中率高得多。用向量相似度判断两个请求是否等价相似度超过阈值就复用结果。但阈值不能太低否则会返回不相关的结果我一般设在0.95以上。模型分级我一般用路由实现先用规则或小模型判断任务复杂度简单任务走便宜模型复杂任务走强模型。实测下来成本能降一半以上质量损失很小。5. 常见问题与排查技巧实录5.1 模型输出格式不稳定怎么办这是最高频的问题。你要求输出JSON它偏要加一段解释文字。解决办法有几个层次Prompt里明确格式要求给出示例、用结构化输出功能很多厂商支持JSON mode、加解析容错正则提取JSON部分、解析失败时重试。我的经验是Prompt示例JSON mode组合能把格式错误率降到1%以下。5.2 响应太慢怎么优化延迟优化要分环节看。如果是模型本身慢考虑换更快的模型或开启流式输出如果是网络慢考虑就近部署如果是编排逻辑慢检查有没有串行的多余调用。流式输出对用户体验提升巨大首Token时间能从几秒降到几百毫秒强烈建议对话类场景都开。5.3 幻觉问题怎么缓解幻觉没法根除只能缓解。常用手段提供参考资料RAG、要求引用来源、降低温度、加事实校验环节。RAG是最有效的把相关知识检索出来塞进上下文模型有据可依幻觉会大幅减少。但检索质量本身也是个大坑召回不准反而会误导模型。5.4 常见问题速查表问题现象可能原因排查方向输出格式错乱Prompt不明确/模型不支持加示例、开JSON mode响应超时模型慢/网络差/逻辑阻塞查耗时分布、开流式成本飙升上下文过长/缓存失效查Token分布、查缓存命中质量下降模型变更/Prompt改动跑评测对比、查版本偶发失败限流/网络抖动加重试、查错误码分布5.5 我踩过的几个坑第一个坑是忽略Token预估有次上线一个长文本总结功能没限制输入长度用户传了篇几万字的文章直接超限报错还扣了钱。后来加了输入长度校验和截断逻辑。第二个坑是评测集和线上分布不一致。评测集里都是标准问题线上用户问得五花八门导致评测指标很好看线上体验却很差。后来我定期从线上日志里采样补充进评测集才慢慢对齐。第三个坑是没做灰度发布。有次改Prompt直接全量上线结果某类问题回答质量暴跌被用户投诉。后来改成先放10%流量观察指标没问题再全量。6. 后续扩展方向这套体系还能怎么用这套从零搭建的AI工程体系跑通之后扩展性很强。往深了做可以接入多模型路由根据任务类型自动选模型可以加Agent能力让模型调用工具完成复杂任务可以做微调用积累的业务数据训练专属模型。往广了做可以把评测、观测能力沉淀成平台供多个AI应用复用。我个人觉得最有价值的扩展方向是数据飞轮把线上请求、用户反馈、评测结果串起来形成持续优化的闭环。用户点踩的回答自动进评测集模型迭代后自动回归验证好的结果反哺Prompt和微调数据。这个飞轮转起来AI应用才会越用越聪明。最后分享一个小技巧把每次线上问题都当成评测集的补充。用户报的每一个bad case脱敏后加进评测集下次迭代就能自动验证是否修复。坚持几个月你的评测集就是最贴合业务的资产比任何公开数据集都值钱。