从零构建AI工程能力:模型接入、Agent开发与上线全攻略
发布时间:2026/10/1 12:59:30来源:尧图网络
去年接了一个项目客户想给内部客服系统加一套AI问答能力。我当时的第一个念头是租一台带A100的服务器从零训练一个大模型——顺着这个思路找了一圈算力资源和训练方案冷静下来后重新算了笔账才真正意识到“AI engineering from scratch”这句话的重量。从零开始做AI工程和从零开始训练一个模型是两条完全不同的路而大多数刚入门的人包括当时的我都容易把这两件事混在一起。这篇文章想写的是我围绕“从零开始搭建AI工程能力”这一整套实践下来的完整思路覆盖从模型接入、提示词设计、Agent开发到多AI协作、测试评估和落地上线的完整链路。适合那些有传统软件开发经验、想切入AI应用层但又不想也暂时不必陷入模型预训练深坑的开发者、产品经理或者独立创业者。文章里所有代码和配置我都跑过属于可以直接拿去用的级别。1. 先分清“训练模型”和“搭建AI系统”1.1 为什么“从零开始”最容易理解错“from scratch”这个词天然带有一种诱惑力让人以为必须从底层把模型、数据集、训练流程全部造一遍才算真正的AI工程。我最初也是这么想的直到认真评估了成本一份像样的预训练语料清洗流程少说两三个月单次训练烧掉的算力费用够一支小团队发一年工资而且训练出来的模型能力大概率追不上已经开源的主流底座。更关键的是就算把模型训练出来了还要面对部署、推理优化、测评对齐等一系列问题那条路不适合绝大多数应用团队。我后来的理解是AI工程的核心任务不是“造模型”而是“用模型”。从零开始做AI工程指的是从零开始构建一套围绕大模型能力的应用系统——你不需要从第一行注意力机制代码写起但你需要从第一条API调用、第一个提示词模板、第一个Agent循环写起。这套系统的复杂度恰恰不亚于训练一个模型只是复杂的方向不一样。1.2 一张认知地图AI工程到底分几层我给团队画过一张分层图后来成了内部所有新人的入门材料这里分享出来模型能力层这是底座包括基座模型的选型、上下文窗口长度、推理能力、多模态能力。这一层的决策决定了上层能做什么。基础设施层模型API接入、私有化部署、向量数据库、缓存、模型路由策略。这一层解决的是“模型服务怎么稳定可靠地暴露给业务层”。应用编排层提示词模板、Agent工具调用、工作流编排、记忆管理、多Agent协作。这一层是AI工程的真正主战场也是大部分从业者最有价值感的领域。产品闭环层评估集构建、自动化测试、日志追踪、成本监控、灰度发布、反馈回收。没有这一层AI应用永远只能停留在Demo阶段。绝大多数人一上来就盯着第一层和第四层之间的巨大落差要么想直接跳到最底层搞训练要么只停留在最顶层写几个Prompt发朋友圈。真正成熟的AI工程团队精力分配大概是我上面这张图倒过来的产品闭环层消耗30%的时间应用编排层消耗40%基础设施层20%模型能力层只需要10%。1.3 学术路线和工程路线的分岔口网上关于《Build a Large Language Model from Scratch》这本书的讨论热度一直很高书确实写得好把从数据集构造、tokenizer、注意力机制、预训练到微调的完整过程讲得很透。但它更适合走算法路线的人——研究模型内部机制或者准备进入大模型训练相关岗位的人。如果你的目标是三个月内上线一个AI客服、一周内给业务做一个文档问答机器人那么照这本书的路径走一步都落不了地。我认识一个做电商SaaS的朋友花了两个月啃预训练相关的资料最后做出来的东西还停留在本地跑通了一个小模型的玩具级推理。后来换了个思路直接用开源底座加RAG一周就交付了第一版可用功能第二周客户反馈就回来了。这就是工程路线和学术路线的真实差距前者在快速试探真实需求的形状后者在试图一次性理解全部原理。两者没有高下之分但你要先想明白自己站在哪条路上。2. 模型接入的三种路径与选型逻辑2.1 托管API最快到达业务层的路径托管API是最适合作为AI工程起点的接入方式。不需要关心显存、推理部署、动态batch只需要一个Key写几行代码就能把大模型能力接进自己的系统。业内主流的托管API我基本都测过包括OpenAI的GPT系列、Anthropic的Claude系列国内的话DeepSeek、通义千问、智谱GLM、Kimi也都有稳定的对外服务。从工程实践的角度多接几家、做一层适配封装而不是吊死在一家上是更稳妥的做法。一个最小可用的调用封装长这样import requests import json API_KEY 你的key BASE_URL https://api.deepseek.com/v1 def chat_with_model(prompt: str, system: str 你是一个严谨、可靠的助手, temperature: float 0.7) - str: payload { model: deepseek-chat, messages: [ {role: system, content: system}, {role: user, content: prompt} ], temperature: temperature } resp requests.post( f{BASE_URL}/chat/completions, headers{Authorization: fBearer {API_KEY}}, jsonpayload, timeout30 ) resp.raise_for_status() return resp.json()[choices][0][message][content]这段代码看起来简单但有几个工程点值得注意。第一个是timeout必须设置LLM的响应时间波动比普通API大得多不设超时会被慢响应拖死整个调用链。第二个是system prompt不要写在代码里写死要放到配置中心或者数据库里这样调整系统人设时不需要重新发布代码。第三个是断点重试机制模型服务偶尔会返回5xx错误配一个指数退避的重试逻辑几乎是必须的。2.2 私有化部署什么时候才值得自己扛开始做AI工程的头两个月我始终绕不开一个问题要不要上私有化部署后来总结出一个判断标准如果数据敏感度要求极高、请求量足够大大到API调用成本已经明显高于自部署的硬件摊销或者业务对网络路径有硬性的隔离要求才值得考虑私有化。如果只是“感觉私有部署更安全”或者“大家都在搞”那就先别碰。以当前生态里比较成熟的本地推理工具Ollama为例部署一个开源模型其实非常轻量ollama pull qwen2.5:14b ollama run qwen2.5:14b从拉取到跑通也就几分钟。但真正的成本在之后你需要关注显存占用、并发吞吐、量化精度损失、上下文长度限制。我实测过7B级别模型在纯CPU环境下的推理速度慢到几乎无法支撑真实业务交互所以私有化部署基本要和GPU绑定这也意味着成本曲线在一个比较高的起点上。工程上还有一种折中方案日常高频、简单的任务走托管API敏感数据相关的任务走私有化部署用一套路由层做分发。2.3 模型路由别把所有鸡蛋放一个篮子真正做了一段时间AI工程之后我发现模型选型不是一次性决策而是持续演进的动态过程。不同模型的擅长领域、价格、响应速度差异很大用同一个模型处理所有类型请求成本上不划算效果上也不是最优。比较常见的实践是搭一个轻量路由层请求过来时先做规则判断短文本分类任务走便宜的小模型复杂推理和长文档任务走更强的旗舰模型需要极低延迟的走专有模型版本。路由判断不一定需要AI参与大部分场景用传统规则就够了。比如请求里检测到“总结这份合同”“对比这两个方案”这类强推理意图时直接路由到强推理模型简单问答、关键词抽取这类任务路由到轻量模型。这套逻辑的实现成本不高但省下的token费用非常可观——我们线上一个业务跑下来通过路由策略成本下降了差不多四成响应时间的中位数也快了近一倍。模型能力不是越强越好适合任务复杂度、成本预算和延迟要求的组合才是好的选型。3. 提示词工程AI应用的第一层地基3.1 为什么提示词值得按工程标准来做很多人觉得提示词就是“跟AI说几句人话”这种想法在个人娱乐场景下没问题一旦进入生产环境就会崩。原因是业务提示词的生命周期远比想象中长——从第一个版本上线到后续的优化迭代中间可能要经历数不清的调整。如果提示词只是随手写在一段代码里没有结构、没有版本、没有测试用例那么每一次调整都是在赌运气。我把提示词工程理解成“面向LLM需求描述的结构化方法”。它的产出物不是一句话而是一份可以被版本管理、被测试、被复用的模板资产。生产环境的提示词应该有明确的层级、稳定的变量接口、可观测的输出格式。这是我做了几个项目之后才悟出来的早期我也是一股脑把需求全部塞进一个系统提示词里结果上线后模型经常出现“答非所问”或者“突发遗忘约束”的情况排查起来极其痛苦。3.2 结构化提示词的R-I-C-E框架我自己整理了一套提示词模板方法内部叫R-I-C-E框架四个字母分别对应角色Role、意图Intent、约束Constraints、示例Examples。角色定义模型以什么身份回答问题意图说明用户来做什么、模型要产出什么约束圈定回答的边界与格式示例则给模型提供具体的输出风格参考。这个框架不是什么学术成果纯粹是从工程实践中揉出来的。一个真实在用的模板长这样# 角色 你是一名资深的软件架构师擅长系统设计评审。 # 意图 用户会给出一个系统设计方案你需要从可扩展性、可维护性、安全性三个维度进行评审并给出结构化的改进建议。 # 约束 1. 每个维度至少指出2个问题最多5个问题。 2. 改进建议必须具体可执行不能只给原则比如要写明“在XX模块引入缓存key设计建议为XX”。 3. 若用户提供的信息不足以支撑评审明确列出缺失信息清单不进行猜测。 4. 输出格式使用Markdown按“优点”、“问题”、“改进建议”三部分组织总字数控制在800字以内。 # 示例 用户输入一个基于微服务的电商中台设计…… 模型输出……这个模板里约束是灵魂。给模型划清楚边界比在对话中反复纠正要有用得多。此外示例的位置也很关键——放在约束之后模型在理解规则后看到了正面的输出示范生成质量的稳定性会明显提高。3.3 温度与采样参数一句参数改变整个性格提示词文本之外采样参数是经常被忽略的第二层控制。temperature控制随机性值越低输出越保守、可复现性越强值越高越有创造性但也越容易跑偏。top_p控制候选词累积概率范围和temperature有相似的调节作用但机制不同实际使用中通常是固定一个、微调另一个。不同任务对参数的偏好差异很大我整理了一个参考表任务类型temperaturetop_p说明代码生成0.0 - 0.20.1 - 0.5代码要精确宁可保守也不可乱造实体抽取/分类0.0 - 0.30.3 - 0.6格式和内容都要严格可控文案创作0.7 - 1.00.8 - 1.0需要一定的发散空间技术问答0.3 - 0.50.5 - 0.8既要准确又保留一点灵活性头脑风暴1.0 - 1.30.9 - 1.0鼓励多样性参数调整的原则是先定任务要求的确定性程度再选参数区间。如果发现输出结果总是“语义正确但格式不稳”优先检查的是temperature是不是设太高了而不是继续堆提示词。3.4 few-shot策略示例的数量和质量比想象中敏感Early on我踩过一个很典型的坑为了提升模型表现我疯狂堆示例一次给了模型二十多个历史good case结果输出质量反而下降。后来研究采样原理才意识到few-shot示例不是越多越好它会挤占有限的上下文空间并且示例噪声还可能把模型带偏。实践中效果最好的是给3到5个高质量示例并且保证示例之间的差异性覆盖各种典型输入形态而不是把相似的case重复贴一堆。选示例的时候要有意识地做困难样本挑选。全是简单case会让模型过度拟合到“常规表现”遇到稍微复杂一点的输入就崩。我在做AI客服辅助工具时会在示例里专门放几个“用户描述含糊、包含错别字、信息不完整”的case让模型学会在面对不完美输入时如何先澄清再回答。这种对困难示例的刻意设计是提示词工程从入门走向及格的关键分水岭。4. Agent开发的入场券工具调用与任务循环4.1 Agent的本质是“让模型拥有操作能力”做完几个纯问答类项目之后我明显感受到单轮对话的瓶颈模型只会生产文本但真实业务需要它“去做事”——查数据库、调用接口、写文件、发通知。如果把模型限制在“只能说话”的框框里再好的提示词也救不了场景覆盖度。所以Agent开发成了我接下来重点突破的方向。Agent和一次性Prompt调用的本质区别在于循环模型不是给出一个答案就结束而是进入“规划 → 调用工具 → 观察结果 → 再次规划”的循环直到完成任务。你可以把Agent理解成一个配备了工具箱的实习生他只擅长思考每一步“动手”都要通过工具完成而你要负责给他设计好工具箱的使用说明书工具schema和做事节奏循环逻辑。4.2 工具调用的Schema设计让模型“学会”调用接口大模型本身不具备调用函数的能力但它可以被“引导着”输出一段结构化的调用指令。主流模型厂商都支持function calling本质是开发者声明一批工具的函数签名模型根据用户请求决定要不要调用哪个工具、参数怎么填然后返回一个结构化结果由你的代码真正去执行。实测下来工具schema写得清不清楚直接决定了Agent的执行成功率。设计工具schema有几点经验。函数描述要写得像给人类同事的交接说明一样具体不要写“获取用户信息”这种模糊描述要写“根据用户ID查询用户在系统中的注册信息、会员等级和最近订单时间用于客服判断用户身份”参数说明要讲清边界比如字符串类型的日期参数要标注格式是YYYY-MM-DD枚举值要全部列出来否则模型经常自己发明数据。一个经过打磨的工具声明长这样[ { name: get_user_profile, description: 根据用户ID查询用户注册信息、会员等级和最近订单时间用于客服身份确认与权益判断, parameters: { type: object, properties: { user_id: { type: string, description: 用户唯一标识格式为纯数字字符串 } }, required: [user_id] } } ]4.3 一个最小Agent循环的骨架实现理解了工具调用之后写一个可用的Agent其实并不神秘。核心就是一个while循环在循环里做四件事把最新的工具返回结果拼进消息历史请求模型判断下一步动作解析模型输出可能是最终答案也可能是工具调用指令执行工具并把结果追加到消息上下文。下面是简化版的骨架代码import json from typing import Callable, Dict TOOL_REGISTRY: Dict[str, Callable] { get_user_profile: get_user_profile, # 真实业务函数 query_order_status: query_order_status, } def run_agent(user_message: str, system_prompt: str, max_steps: int 5) - str: messages [ {role: system, content: system_prompt}, {role: user, content: user_message}, ] for _ in range(max_steps): resp call_model_with_tools(messagesmessages, toolsTOOL_SCHEMAS) msg resp[message] # 情况一模型给出的是最终回答 if not msg.get(tool_calls): return msg[content] # 情况二模型要求调用工具 messages.append({**msg, content: None}) for call in msg[tool_calls]: func TOOL_REGISTRY[call[function][name]] args json.loads(call[function][arguments]) result func(**args) messages.append({ role: tool, tool_call_id: call[id], content: json.dumps(result, ensure_asciiFalse) }) return 已到达最大步骤数任务未完成这段代码跑通了一个核心闭环但距离生产还有一个关键问题max_steps循环里如果模型反复调用同一个工具、拿同一个结果就形成了死循环。我一般在每次循环里加一个简单的状态检查记录最近三步的调用结果如果模型重复请求相同参数的工具调用直接打断并引导它基于已有信息给出结论。4.4 记忆管理Agent的上下文不能无限膨胀Agent循环次数一多消息列表会越来越长上下文窗口很快被占满而且越靠后的信息对模型的注意力影响越大早期的关键信息容易被稀释。记忆管理成了Agent工程质量的关键点。我的实践分三层对话滑动窗口只保留最近N轮对话防止基础膨胀工作摘要记忆每一轮工具调用结束后让一个快速模型生成本轮摘要把摘要追加到上下文中长期知识检索把关键的业务实体信息定期写入向量库在需要时通过相似度检索重新召回。三层配合使用既能控制token消耗又能保证Agent在复杂任务中不会“失忆”。这里有一个比较容易忽略的细节摘要模型和主Agent模型的上下文不能混为一谈摘要如果写得过于精简丢失的细节反而会误导Agent。我踩过这个坑之后把摘要的要求改成了“保留所有数字、名称、状态和结论”信息丢失率明显降低。5. 多Agent协作把单点能力串成生产线5.1 单Agent的极限与多Agent的动机Agent单点能力再强也逃不过两个问题一是单个Agent的提示词上下文会被越来越多的职责稀释让它既要会理解客户情绪又要能查数据库还要能写回复每一项都做不精二是很难用一套参数和模型适配所有子任务的最优需求。这时候多Agent协作的价值就出来了——一个系统里不同的Agent各司其职分别拥有独立的提示词、独立的模型选型、独立的上下文窗口它们之间通过消息传递完成工作交接。我用一个内容生产流水线举例。传统做法是写一个超级Agent输入“帮我出一篇关于智能家居的评测文章”它从头写到尾中间几乎没有过程控制和质检。多Agent的做法是拆成五个角色策划Agent负责分析受众和选题角度产出文章大纲资料Agent按照大纲检索素材整理成要点清单写作Agent根据大纲和素材完成初稿评审Agent扮演刁钻读者提出修改意见编辑Agent根据意见做最后修订和格式优化。5.2 消息协议Agent之间怎么说话多Agent协作的工程重点不在每个Agent本身的实现而在于它们之间的消息传递格式。实际项目中我倾向于定义统一的中间产物协议用JSON格式在各个Agent之间流转而不是直接传递自然语言。比如策划Agent的输出是这样一份结构化数据{ title: 2025年智能家居选购指南, target_audience: 对新装修家庭有智能家居配置需求、预算约2-5万的用户, core_angles: [性价比组合, 生态兼容性, 安装易用性], outline: [ {section: 引言, key_points: [为什么现在适合入手, 文章将解决什么问题]}, {section: 预算分配, key_points: [不同价位段的组合方案, 推荐优先级]} ] }下游的写作Agent不再需要自己琢磨选题角度和文章结构它只需要接收这份JSON然后专注于“把它变成一篇好文”。每一层Agent的输入输出边界清晰之后整个系统就可以单独替换任意一环——换一个更强的写作模型不动其他环节给策划Agent加一个热点检测工具也不影响下游。5.3 工作流引擎的选型从Dify到LangGraph多Agent协作逻辑复杂起来之后自己手写编排代码开始变得吃力分支、重试、并发的逻辑散落在各处维护成本快速上升。这时候值得引入工作流引擎。国内社区里比较成熟的可视化方案有Dify和Coze国外常用的有LangGraph和Temporal。我的选型经验是业务团队想快速看到效果、且非技术人员也需要参与配置的优先看Dify图形化编排对团队门槛低插件生态也够用技术团队主导、需要深度定制状态机和精确控制循环逻辑的选LangGraph这类代码优先的框架。不管用哪个引擎核心编排思想是一致的Agent之间的调用关系被抽象为节点和边节点是具体的Agent或工具动作边是流转条件。串行适合有严格先后依赖的工序并行适合互不依赖的独立子任务条件分支则根据前一步结果决定下一步走向。我在流水线里把资料检索和用户画像分析做成了并行节点两个Agent同时跑总耗时直接砍半。这类优化听起来不大但在生产环境里就是实打实的体验提升。5.4 编排中容易踩的稳定性坑多Agent协作系统上线后我遇到的最典型问题是“错误传导”。上游Agent偶尔的一次信息偏差经过多轮传递之后会被下游Agent当作事实基础最终输出完全走样。后来我在每个Agent的输入提示词里都加了一行强约束若上游提供的信息中存在明显缺失或矛盾禁止自行脑补必须在输出中显式标注“信息存疑”。同时在Agent间的消息协议里增加了一层“来源标注”每个字段都记录是哪个上游Agent在哪个步骤生成的出了问题可以精确回查。另一个问题是token成本呈指数级增长。一次完整的多Agent协作总token消耗可能是单Agent调用的五到十倍。应对手段有三板斧尽量复用中间结果做缓存相同输入的大纲生成不重复调用并行节点合并小模型任务对低风险的中间环节使用更便宜的轻量模型。成本控制不是事后核算而是要在架构设计阶段就纳入约束条件。6. 测试、评估与上线AI工程闭环的最后一公里6.1 没有测试集就没有优化依据业务系统上线前要写单元测试、集成测试但AI应用经常被当成“没法测试”的特例。这是我早期最大的盲区。AI的输出具有概率性传统断言方式确实不适用但不代表不能测试。正确的做法是建评估集Eval Set收集一批代表性用户输入为每条输入标注理想输出标准或关键要素然后让系统在同样的输入上跑一遍用规则或模型来判断输出质量。评估集不需要一开始就做到面面俱到我的建议是二十个golden case起步覆盖三种类型核心业务场景的成功路径、容易被绕过的边界与负面case、需要模型明确拒绝的违规输入。随着线上真实反馈积累评估集逐步扩充每次改动提示词或更换模型之后都拿评估集整体回归一遍。就这样把“感觉变好了”变成“指标变好了”AI应用的迭代才进入正循环。6.2 自动化评估的落地方案自动化评估的做法分层递进。第一层是规则断言检查输出是否包含必要字段、长度是否合规、格式是否为合法JSON这类检查最简单也最可靠。第二层是关键词与语义标注判断回答是否覆盖了评估标注里的核心要点。第三层是用一个独立的“评审模型”对生成结果打分输出结构化评分和理由。不同层级的成本和准确度差异明显理想状态是一层一层叠加而不是一上来就用评审模型代替全部检查。一个简易的评估脚本骨架如下def evaluate_response(input_text: str, response: str, required_points: list) - dict: results {} # 第一层格式与结构检查 results[valid_json] is_valid_json(response) results[length_ok] 100 len(response) 2000 # 第二层关键要素命中 missing [p for p in required_points if p not in response] results[coverage] (len(required_points) - len(missing)) / len(required_points) # 第三层评审模型打分 judge_prompt f...需要补充评审模型的完整指令... judge_score call_judge_model(judge_prompt) results[judge_score] judge_score return results第三层的评审模型指令是这套方案能否成立的关键写法和前文的提示词工程方法论一致要让评审模型明确“按什么标准打分”“多少分算合格”“什么情况必须一票否决”。我给评审模型设置了一票否决项——比如回答中包含编造的数据、答非所问、或者直接暴露系统提示词内容不管其他指标多好这条case直接判失败。6.3 可观测性建设给AI系统装上仪表盘AI应用上线后黑盒运行是最大的隐患。提示词模板被命中多少次、某类请求的模型响应平均耗时、工具调用失败率、单次会话平均token消耗、用户对回答的点击反馈——这些数据必须全量采集。我的实践是在所有模型调用入口统一封装一个日志模块每次调用记录模型名称、输入摘要、输出摘要、耗时、token数、成本估算、关联的业务ID统一写入日志管道再对接到可视化看板。这套观测体系的直接价值是某个模型供应商的服务变慢时能从日志中立刻定位是哪类请求受影响并且快速切换路由某个提示词模板改完之后回答质量下滑可以通过评分数据直接对比版本差异。没有观测数据优化全靠玄学有了观测数据每个决策都有据可循。6.4 灰度发布与人工复核兜底AI系统的上线要慎之又慎直接全量切换是危险操作。我的标准流程是先在内部小范围试用再开放给5%的真实用户流量观察评价数据和用户反馈确认稳定后再逐步放大到30%、70%、100%灰度发布是AI工程里性价比最高的风险管理手段。每一步放量之间至少要间隔一个完整业务周期确保能看到不同时段、不同用户群体对系统的真实使用情况。灰度期间的人工复核兜底同样不能省。对于客服辅助、内容生成这类涉及业务合规的场景在系统输出之后、正式发送给用户之前保留一个人工确认步骤是完全值得的。机器先生成人只负责审核和放行带来的成本增加有限但避免了大量潜在的业务风险。等到系统评分持续稳定在一个较高标准后再逐步降低人工抽检比例。做了一段时间之后回头总结我对“AI engineering from scratch”最大的感受是真正的难点不在某个单点技术有多深而在于把这套链路中的每一个环节都当成工程问题来对待——选型要有依据提示词要能维护Agent要可控评估要可量化上线要有灰度。这和你做任何一款成熟软件产品的逻辑是一样的只不过调度对象从一个确定性的代码库变成了一个概率性的模型。最后分享一个小技巧起步阶段别一上来就铺多Agent、上工作流引擎、搞一套大而全的平台。先用手写代码把一个最小业务闭环跑通哪怕是最傻的单次Prompt调用都行然后再逐步加入工具调用、评估集、观测日志、协作编排。每一步都基于真实暴露的问题去演进而不是基于想象去设计。这套从零开始的路子至少帮我避开了无数轮无效的过度设计。
网站建设高端定制企业官网