ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零构建AI工程:约束、评测、观测与成本的实战指南

从零构建AI工程:约束、评测、观测与成本的实战指南 作为从传统研发转过来的工程师我第一眼看到ai-engineering-from-scratch这个标题时心里其实打了个问号。过去一年里市面上关于AI开发的讨论很多但绝大多数内容要么停留在猜Prompt的层面要么是某个框架API的快速上手手册。真正能回答如果今天我要从零开始构建一个AI工程系统应该怎么设计、怎么选型、怎么保证质量、怎么防坑的内容反而是稀罕东西。我带着这个问题把自己过去一年从玩具项目到生产系统的经历重新复盘了一遍整理出这篇偏向实战的笔记希望能给正在入局或准备入局的同行一些参考。1. 首先得搞清楚AI工程和普通软件开发到底差在哪很多人第一次接触AI工程时会想当然地把它理解成给大模型写Prompt然后用HTTP包一层API。表面看确实像但一旦进入生产环境差异会迅速显现出来。最核心的一点是传统软件的逻辑是人写的、可预期的而AI应用的行为是模型推断出来的、概率性的。这意味着你没法用单元测试覆盖率高质量好那套思路来交付一个AI功能必须重新建立一套工程方法论。1.1 传统研发的确定性在这里彻底失效我举个例子做个电商订单系统你给用户下单这个函数传入合法的用户ID和商品ID返回值是确定的要么成功要么失败边界条件事先可以枚举。AI工程则完全不是这样。你给大模型一段用户问题、几份参考文档和一条系统提示词今天返回的结果和明天返回的结果大概率不一样哪怕Prompt一行都没改。模型版本升级、推理参数波动、甚至上下文里的标点符号都可能让输出漂移。这就带来了一个很现实的转变AI工程的第一性原理不是精确控制而是约束不确定性。你没有办法让模型永远输出对的内容但你可以通过工程手段把错误概率压到可控范围并在出错时快速发现、有效兜底。这个思维转变是很多从传统研发转过来的工程师最难适应、也最需要尽早迈过去的一道坎。我看到不少团队在立项时兴致勃勃觉得接入GPT-4级别的模型后产品就智能了结果上线第一天就翻车模型把用户的退单指令理解成下单客服那边炸了锅。原因很简单他们拿传统软件的设计习惯去套AI应用没有输出校验、没有意图兜底、没有人工确认环节。所以这篇文章不想急着罗列框架和API而是先把底层的工程认知掰扯清楚。1.2 AI工程的最小闭环远不止调接口要构建一个合格的AI工程系统我认为至少需要跑通这样一个最小闭环场景定义、上下文工程、模型调用、结果校验、反馈回流。它不是一条从A到B的直线而是一个持续迭代的环。场景定义解决这个功能到底要解决什么问题上下文工程解决模型需要哪些信息才能正确回答模型调用解决用哪个模型、什么参数、怎么省钱结果校验解决模型输出怎么保证格式合法、内容不越界反馈回流解决线上的坏案例怎么变成下一轮的训练或Prompt优化素材。这个闭环里任何一环缺失系统都撑不了多久。现实中我看到最多的缺失是反馈回流。很多团队做完前四步就急着上线发现模型回答质量下降后也无从下手只能靠人工一条条看日志效率极低。而在生产环境里一个完善的评测和回流机制往往决定了一个AI项目能活多久。2. AI工程的核心技术栈不是单点能力而是整套配合聊到具体落地时很多人会急着问用LangChain还是LlamaIndex微调还是RAG。这些问题都指向了同一个真相AI工程根本没有银弹它是一个由多个能力件组合起来的系统。下面这四块是我认为from scratch构建AI工程绕不开的基础件。2.1 Prompt工程从玄学变成可迭代的工程工艺Prompt engineering可能是AI工程里最被高估也最被低估的部分。说它被高估是因为满屏都是万能提示词模板五个技巧让GPT输出完美答案说它被低估是因为大多数人只把它当写提示词而不是当成一套上下文结构协议来设计。我在生产项目里的做法是把Prompt拆成固定的元信息区角色、任务目标、输出格式、动态拼接区用户输入、检索命中片段、约束边界区禁止行为、兜底话术、引用规则三个段落。这么做的好处是每次模型输出出问题时我能快速定位是角色没立住、还是上下文污染了、还是边界没有约束紧而不是对着一个600字的大杂烩反复猜。举个例子我要做一个客服系统的意图识别模块。第一版Prompt是判断用户意图输出JSON结果模型在模糊场景下摇摆不定。迭代后我把输出层拆成意图编码、置信度、需要补充的槽位、兜底应答建议四个字段并且对每个字段写清楚取值边界。模型的表现立刻上了一个台阶不是因为提示词更华丽而是把原来隐式的任务显式拆解成模型容易遵循的结构。可以给一个精简的Prompt工程模板作为参考## 角色 你是一名资深客服助理负责识别用户意图并返回结构化结果。 ## 任务 判断用户本次消息的真实诉求归类到以下意图之一[退换货, 物流查询, 价格咨询, 投诉建议, 闲聊] 如果意图不明确输出 uncertain。 ## 输入格式 用户消息{user_message} 对话历史{chat_history} ## 输出格式 严格输出 JSON字段如下 {intent: ..., confidence: 0.0~1.0, missing_slot: ..., reply_suggestion: ...} ## 约束 - intent 只能从给定枚举中选一个 - confidence 低于0.6时必须把 intent 设为 uncertain - 不要编造不存在的订单信息这个Prompt的核心价值不在于写得好而在于它把输出变成了可解析、可校验、可降级处理的结构化数据。我见过太多团队栽在让模型自由发挥上自由发挥在Demo里很惊艳在生产里就是灾难。2.2 RAG的胜负手在检索质量而不在模型本身RAG检索增强生成已经成了AI工程里的标配但很多人的认知还停留在切文档、向量化、塞进向量数据库、召回TopK丢给模型这四步。这个流程没错只是太粗糙。真正决定RAG效果上限的是切分粒度是否匹配业务语义和召回内容是否精准命中答案所在片段。切分这件事我踩过很深的坑。一开始图省事按固定512个字符硬切结果一段用户手册里保修条款被拦腰斩断模型拿到的是半截子话回答自然前言不搭后语。后来改成按语义块切结合标题层级和段落边界命中率提升非常明显。实测下来切分策略对回答质量的提升比换一个更强的模型还明显这一点很多刚接触RAG的人很难第一时间体会到。召回的优化也不能只依赖向量相似度。我的经验是向量召回关键词召回重排序三件套才是可生产的最小配置。纯向量召回在语义相近但表述不同的场景下会漏掉关键命中加一层BM25关键词召回做互补再用交叉编码器模型比如bge-reranker对候选集重新排序最终的TopK片段质量会稳很多。这套组合比单靠一个向量库多不了几次调用但效果差距肉眼可见。方案召回精度延迟实现成本适用场景纯向量召回中低低低内部知识库Demo、低并发原型向量关键词中低中文档类型单一、对精度要求尚可向量关键词重排高中中高客服、医疗问答、法律检索等精度敏感场景2.3 Agent编排先从小闭环做起别一上来就画巨型流程图Agent是热搜词里的当红炸子鸡。但在生产环境里我见过太多为了Agent而Agent的设计让模型自主决定调用十几个工具运行链路动不动几十步结果模型在第五步就迷路了。真正务实的做法是给Agent一个最小可用循环——理解任务、检索可用工具、执行动作、观察结果、决定下一步并且每一步都要用代码做硬约束不能全靠模型自觉。我做过一个需要多步操作的内部工单处理Agent。第一版设计是开放所有工具给模型自由调用结果模型经常在查余额和生成报价单之间反复横跳浪费token还出错。后来我把工具调用权限按角色划分普通查询Agent只能读不能写只有审批Agent能调用写操作且写操作前后必须输出明确的变更说明。这个约束一加稳定性立刻上来了。所以对于Agent我的建议是先用子Agent完成单一任务、任务之间用代码编排再逐步扩展到计划-执行-反思的复杂循环。每一步都要记录模型看到了什么、决定做了什么、结果是否符合预期这个trace日志是后期排查问题的重要依据。Level越高的自主性需要的约束和观测能力就越多别让模型承担它不该承担的决策责任。2.4 评测体系没有评估标准一切优化都是空谈评测是AI工程质量的根本保障也是最容易被忽略的部分。很多团队上线了功能才发现感觉变笨了但拿不出任何数据支撑只能靠感觉去调Prompt调完也不知道是变好了还是变坏了。我从实际项目中得到的经验是AI工程的评测体系至少要分三层单测级给定固定输入断言输出格式和核心内容是否满足要求、场景级一批覆盖典型业务路径的测试集跑完整流程看成功率、线上抽检级从生产日志里随机抽样本人工标注后观察指标趋势。这三层不是替代关系而是层层递进。场景级的测试集建设我会把常见的失败案例按类型分组放进回归集里。比如客服系统里金额计算时效承诺退换货政策各建一组每改一版Prompt或检索策略就跑一遍全套回归。一次全绿再放线上。这句话说起来简单真正做到位的团队在行业里其实不多但恰恰是这些团队能持续迭代出质量更高的产品。3. 从零搭建一个AI工程项目的完整实战路径前面讲的都是底层认知和技术栈拆解这一节进入具体操作层面。我以构建一个基于企业知识库的智能问答系统为例子走一遍从设计到落地的完整过程顺便把环境准备和代码骨架一起给出。3.1 环境准备选型和安装里最容易忽略的细节项目开始的第一步是拉环境。我推荐的起步组合是Python 3.10、LangChain或LlamaIndex用于编排、Chroma或Milvus用于向量存储、FastAPI用于服务封装。之所以选这一套是因为它们的社区活跃度最高遇到问题更容易找到解决方案对新手相对友好。环境准备最常被忽略的是向量化和模型调用的版本兼容问题。装依赖时不要无脑装最新版。我自己的习惯是先锁定大版本再根据自己的模型服务商SDK版本做兼容测试。比如OpenAI的openai包从0.x升到1.x时接口变动很大不少项目就是升级后一夜之间全线报错。建议所有依赖写进requirements.txt或者pyproject.toml里并且锁死版本范围别给线上部署留隐患。另外强烈建议做好密钥管理不要把API Key硬编码在代码里更不要提交到Git仓库。用环境变量或者密钥管理服务比如Vault、KMS来处理。这个坑几乎每个AI工程师都踩过——GitHub的爬虫会扫描公开仓库里的密钥你的账单不出三天就会多出几位数。3.2 系统骨架把上下文工程、模型调用和检索层拆开一个可维护的AI工程系统第一原则就是分层。我习惯至少拆成三层数据接入层负责文档解析、清洗、切分、检索与上下文组装层负责向量化和召回拼接、模型调用与校验层负责Prompt渲染、LLM推理、输出解析。拿知识库问答来举例# retrieval.py - 检索与上下文组装层 from langchain_community.embeddings import OpenAIEmbeddings from langchain_community.vectorstores import Chroma def build_retriever(docs): # 先对文档做语义切分再向量化和入库 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma.from_documents(docs, embeddings) return vectorstore.as_retriever(search_kwargs{k: 5})这层最不该做的事就是把业务逻辑写进去。检索层只负责根据问题找到最相关的片段至于模型该怎么组织答案是下一层的事。把职责理清楚后续替换组件时才能不动筋骨。模型调用层我习惯封装一个统一的函数把系统Prompt、用户问题、检索片段拼接好然后调用LLM对输出做JSON解析。一旦解析失败要有重试和降级逻辑不要直接让整个服务崩掉。# llm.py - 模型调用与输出校验层 import json from openai import OpenAI client OpenAI() def call_llm(system_prompt, user_content, fallback我暂时无法回答这个问题。): try: resp client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: system_prompt}, {role: user, content: user_content} ], temperature0.2, response_format{type: json_object} # 强制JSON输出强烈推荐 ) parsed json.loads(resp.choices[0].message.content) return parsed except Exception as e: # 打日志、走降级策略而不是静默失败 logger.error(fLLM调用失败: {e}) return {answer: fallback, error: str(e)}这里有两个细节我吃了不少亏才意识到有多重要。第一是response_format如果你的模型服务商支持强制结构化输出一定要用这能让后面解析层的故障率下降一大截。第二是temperature问答类场景我通常调到0.2以下减少无意义的花式表达创意生成类场景再调高到0.7以上两者完全不同。3.3 第一个可用的Demo之路先跑通端到端再谈优化入门的最大敌人是完美主义。我见过很多新手花了两天研究用什么向量数据库、什么Embedding模型、什么微调方案结果一行代码都没跑起来。我的建议是先用最简路径跑通端到端——加载PDF、切分、向量化、检索、问一个最简单的问题、看到模型输出。哪怕回答质量一般这个过程你已经完成了AI工程的60%。跑通之后再逐项优化先优化切分策略再看召回命中率再调Prompt结构最后才考虑是否微调或换更强的模型。这样每一步都有测试集把关也能清楚知道每次改动到底带来多少提升。反过来一上来就上全套大而全的架构出了问题反而不知道从哪查起。3.4 model selection根据需求选模型而不是只追最强选模型这件事我见过两种极端一种是无脑用最强型号不管什么任务都上最贵的另一种是盲目追求轻量级结果效果没法看。理性的做法是根据任务的复杂度和容错率来安排。客服问答、信息提取这类任务我一般用中等档位的模型类似GPT-4o mini或Claude Haiku级别就够速度快、成本低。对复杂推理、代码生成、长文本总结这类任务再动用高档次模型。更精细的做法是路由分发先用一个轻量模型做意图分类简单问题走便宜模型复杂问题再升级整套下来成本能省40%以上效果还不掉链子。我做一个工具实测过成本对比同样是100万次客服问答调用用最强档模型的花销大约是使用中等档位加路由分发方案的9倍而用户满意度几乎持平。数字背后说明的不是模型不重要而是用对地方比用贵的更容易带来工程收益。4. AI工程的质量关卡可观测和评测体系是保命底牌跑通Demo不难难的是让系统在生产环境长期稳定运行。这一节我把AI应用上线后最关键的几个质量关卡展开讲讲这些都是传统研发里没有、或者说很少去重仓投入的环节。4.1 每个AI能力都要有可控性设计所谓可控性设计就是给系统加上各种制动阀让模型在不该过分自由的时候能被强行拉回来。具体落地包括输出模式限定JSON Schema校验、设定不确定性阈值低置信度时走人工兜底、敏感操作要二次确认不能模型说改就改、在关键链路上加入代码断言。比如在线客服系统里模型给出的回复如果带出个人信息或内部数据必须被代码拦截并替换为通用话术。这个不是靠Prompt里写不要泄露数据就能保证的必须在系统层面用正则、白名单或者语义过滤做一道硬校验。我见过一个真实的翻车案例模型在调试日志里读到了内部数据库地址然后在一个正常回答中把这串主机名带了出来完全没有违规意图就是上下文里看到了就顺手写上了。读日志和输出校验是两码事出问题的一定是缺了后者。在代码里我习惯给每个可能出错的环节都设置降级路径def generate_safe_answer(query, context): parsed call_llm(system_prompt, query, context) # 安全过滤与格式断言 if not parsed.get(answer): raise ValueError(模型未返回答案字段) if contains_sensitive_info(parsed[answer]): parsed[answer] 抱歉我暂时无法提供相关信息。 return parsed4.2 可观测性AI日志比普通日志多一个维度传统系统的日志关注请求参数、状态码、耗时、异常栈基本就够了。AI系统的日志还必须多一个维度——内容。你需要记录模型实际收到了什么上下文、生成了什么内容、用户对结果的反馈是什么。没有这些线上问题你连复现都做不到因为模型是概率性的同一个输入第二次跑可能结果完全不同。我目前的生产日志至少会包含这些字段请求ID、会话ID、用户问题、命中片段ID列表、Prompt版本号、模型版本、推理参数、原始输出、解析后输出、耗时、token消耗、是否走了降级路径。这些数据不只能排查问题还能沉淀成评测集和优化素材一鱼两吃。另外一个容易被忽视的是版本管理。Prompt不是写一次就完事它和代码一样需要版本化。每次修改Prompt都建议连同对应的评测结果一起记录。我习惯在路上每个功能的Prompt维护一个变更表记下改了什么、为什么改、评测集跑分变化、线上效果观察。否则三个月后你根本不知道当前Prompt为什么会变成这副样子。4.3 LLM评测体系的搭建顺序和实际案例评测体系的搭建我建议从抠细节的单元评测开始而不是一上来就搞复杂的人工标注平台。第一步准备30-100条固定问题覆盖每个核心功能点写好期望输出规则第二步写一个评测脚本自动跑完这批问题输出通过率第三步每次改动后先跑脚本再决定要不要上线。等团队熟悉这个流程后再引入线上抽检和人工标注打分。模型输出的质量有时比传统软件的接口返回更难量化所以评分标准我会尽量落到可观测的行为上例如是否引用了正确文档是否包含错误日期是否推卸责任等越具象越好。拿一个实战数据来说我做一个内部AI助手时第一版评测通过率只有62%看着很差。但正是因为有这62%的基线之后每次改Prompt、换切分策略、调重排序都能明确知道提升了几个点。经过三轮迭代做到87%当时再上线心里就有底多了。没有基线的优化只能叫碰运气有基线的优化才叫工程。4.4 成本控制用工程手段把token花在刀刃上大模型API的计费逻辑决定了AI应用的成本和token消耗强相关。成本控制不是上线后再优化的而是架构阶段就要考虑。常见的有效手段包括使用缓存相同的用户问题命中缓存后直接返回历史答案、优先用小模型做初筛、控制上下文长度别把不相关的内容一股脑塞给模型、对长文档做摘要预处理再让模型回答。我实测过接入语义缓存后重复问题占比高的客服场景API成本能降40%左右而用户几乎感知不到差别。另外上下文长度的控制也很有讲究。很多团队觉得能塞的都塞进去模型能处理却忽略了每一轮对话都在为超长上下文付费而且过长上下文还可能引入噪音、降低回答准确率。我的习惯是先做召回过滤精选Top5片段拼接控制总长度在3000字以内再让模型回答省钱且效果更好。5. AI工程化的下一步从个人技巧到团队协作范式聊完了技术细节最后想谈谈更宏观层面的东西。AI engineering发展到现在已经不只是一个人的工程技巧而是在逐步沉淀为一套团队协作范式。这个转变是否顺畅往往决定了一个组织能在这个领域走多远。5.1 harness engineering是什么给模型能力和团队协作戴上缰绳热搜词里出现的一个概念“harness engineering”值得认真对待。直译过来是约束工程或缰绳工程它强调的是大模型的能力再强也必须被套进一套可控的框架里——包括明确的输入输出协议、内部工具的访问边界、责任审计和熔断机制。一个有具体场景的AI系统不只是模型经过编排后的产物更是一套组织能力沉淀的流程。我在团队里推行这套理念时落地成三样具体的东西功能请求模板、模型变更评审表、上线前的检查清单。功能请求模板要求任何人都能说清楚这个功能的用户场景是什么、当前方案的缺陷是什么、模型参与哪一步决策、失败时如何兜底模型变更评审表用来记录模型版本升级前后的评测对比上线检查清单则纯粹是把可控性设计里那些容易忘的硬约束全部列在上面逐项打勾。这些流程看着繁琐但真正救过我一次。当时我们把一个核心模型从旧版升到新版上线前跑一遍评审表发现新版在时间表达理解上误判率明显升高差一点就带着这个隐患直接上了线。没有评审流程这种回归问题靠肉眼很难提前发现。5.2 与AI编程工具/测试开发环节的协同AI工程化离不开研发环节本身的效率提升。现在行业内已经有大量AI编程辅助工具能帮工程师自动生成夹具、生成单元测试、解释报错信息等。我的体会是这些工具的核心价值不是替你写代码而是帮你缩短从想法到验证的反馈循环。简单的函数、样板代码、数据结构定义这类基础工作AI生成后人工确认效率提升非常明显。但AI编程工具要辩证去看。生成代码的质量取决于描述质量而描述质量又取决于工程师的抽象能力。我见过同事让AI写两百行代码结果最后删掉重写的也不少。关键是要把AI定位成结对搭档而不是外包工人你负责拆解需求和把关质量它负责加速打字和列举方案。想清楚人和模型的分工边界AI才能真正成为研发流程的杠杆而不是新负担。在AI测试开发环节也一样用大模型生成测试用例和测试脚本写得很欢但这些样本必须经过严格的人工审核和场景拟合。尤其涉及边界条件和异常注入时大模型生成的用例往往太平滑、太理想对真实环境里的脏数据缺乏想象力。正确姿势是拿线上真实日志里的坏案例去喂测试集而不是依赖模型凭空想象。5.3 从Demo文化到工程文化的转变最后想聊一个文化层面的坑。很多团队做AI项目时习惯于拿着Demo去汇报因为Demo天然适合讲故事。但Demo文化一旦占据主导会让团队忽视那些最不性感但最重要的工程环节评测集建设、可观测性、安全过滤、成本控制。我自己的感受是AI工程文化的核心不是把AI用起来而是让AI用得住。用起来只需要一个下午和一次API调用用得住则需要一整套从设计、开发、评测、部署到监控的体系。这套体系不会让Demo更惊艳却能让项目活过半年、一年而不会被一次线上事故打回原形。回到标题ai-engineering-from-scratch我的看法是从零开始构建AI工程真正的起点不是某个框架的安装命令而是你对约束、评测、观测、成本这四个词的理解有多深。技术栈会持续迭代模型会更聪明但这套工程底座会一直是你做AI应用最值钱的家底。
返回列表