资讯动态

AI工程从零到上线:提示词、Agent与可观测性的实战指南

发布时间:2026/9/30 4:06:52 来源:尧图企业网站定制
去年我花了两个完整的周末把一个只有一段需求描述的AI应用从零推到可以稳定服务真实用户的线上版本。第一个周末搭出了能跑通的雏形第二个周末把可靠性和成本砍到能接受的范围。期间踩过的坑、推翻重来的模块比正常业务系统开发多得多。今天这篇东西就是把“AI工程从零开始”这点事按我真实走过的路径从头捋一遍。这几年挂在嘴边的词从“人工智能”变成了“AI工程”这不是换个叫法那么简单。真正拉开差距的不是谁调的提示词更花哨而是谁把不确定性极高的模型输出封装成了一套稳定、可测、可维护的系统。下面拆开讲。1. 先搞清楚“AI工程”到底在解决什么问题1.1 它和传统软件开发有什么本质区别传统软件开发的基石是确定性同样的输入同样的代码几乎必然得到同样的输出。你可以写单测、做断言、建立回归体系因为函数行为是可复现的。AI工程面对的是概率性机器同样的提示词同样的输入模型可能给出不完全一样的回答有时候还会犯错、会编造、会偏离指令。我记得第一次把AI能力集成到业务逻辑里时最不适应的就是没法用传统单测思路去验证“这个功能是对的”。你只能验证“在给定输入下输出是否满足约束条件”而不是“输出是否等于期望值”。这是思维方式的一个大反转。所以AI工程的核心命题不是让模型“每次都对”而是构建一层工程壳子把模型的概率性行为约束在我们能接受的范围内并在它出错时能及时发现、优雅降级。传统工程追求“消除意外”AI工程追求“管理意外”。1.2 从零起步需要具备哪些底子先泼一盆冷水不是完全零基础也能直接上手但有几条底线必须够得着。Python基础语法和常用库requests、json、dataclass这类要顺手基本的HTTP和接口调用概念要理解因为你早晚要跟各种模型API、第三方服务打交道数据结构里至少要明白列表、字典、树和图的差别做Agent的时候会用到如果要做复杂一点的流程编排还要懂一点事件循环和异常处理。如果这些都不熟建议先花一到两周补齐再去碰模型相关的代码。我见过不少朋友跳过基础直接抄Agent框架最后连日志都看不懂排错举步维艰。反过来也不需要去啃完机器学习理论。AI工程和算法研究是两条路工程侧重调用、编排、评测、防护不需要从头推导反向传播。把精力花在应用层面的架构和组织能力上比死磕数学公式性价比高得多。2. 搭建属于你自己的AI工程环境2.1 工具链选型从命令行到代码编辑器的完整组合AI工程日常开发其实不太依赖重型IDE我个人的主力组合很朴素VS Code加Python插件终端里跑脚本和实验必要时用uv管理依赖。跟那些重度使用Jupyter的同事比我更喜欢从一开始就把代码组织成可执行的工程避免Notebook里改来改去、到头来没法复现的麻烦。Python版本我建议直接上3.11或3.12别用太老的版本一些新的异步框架和类型提示特性在老版本上会碰壁。虚拟环境管理工具我目前推荐uv它比pip加venv快一个量级锁依赖也干净。早期用poetry也行但团队协作时解析依赖的速度会让人抓狂。如果你只是快速验证一个想法也可以先把代码写在单文件里跑通再拆模块。但注意这个“先写单文件”的阶段不要拖太久一旦脚本超过三百行就开始重构否则后面接工具、接记忆、接评测时会非常痛苦。2.2 模型接入方案API调用、开源模型与本地部署怎么选做AI工程绕不开模型选型。我的判断框架很简单优先考虑质量、成本和隐私三个维度。当业务允许调用云端服务且对延迟不是极度敏感时直接用成熟的开源或商业模型API这是最快路径当数据有隐私约束或者长期调用成本太高时考虑私有化部署小参数模型当需求非常垂直时千万不要为了“用上开源模型”而放弃效果先在最好的模型上验证效果再考虑降级到小模型并做蒸馏或微调。这里要强调一个常见误区很多人一开始就本地部署一个7B模型然后抱怨效果不行。实际上中小团队做AI工程最优策略永远是“先用最好的模型把流程跑通确定天花板再做降级优化”。千万别在方案验证阶段就为了省钱或者为了“私有化”牺牲效果那是本末倒置。2.3 工程目录与依赖设计让项目从一开始就能被维护聊完选型说一个非常实在的东西工程目录怎么设计。我做AI项目有个默认结构长期用下来很顺手project/ app/ main.py # 入口与调度 agent.py # Agent核心逻辑 tools/ # 工具函数 prompts/ # 提示词模板 __init__.py system.txt user.txt memory/ # 记忆与状态管理 tests/ test_agent.py eval_set.jsonl # 离线评测集 config/ settings.py # 参数配置 logs/ requirements.txt为什么把prompts单独拎出来因为提示词在AI工程里跟代码一样重要它需要版本管理、评审、回滚。把提示词硬编码在业务逻辑里是灾难后面改一个标点符号都得动代码。依赖管理方面我的建议是凡是模型API的参数模型名、温度、max_tokens全部收敛到config模块里不要散落在各处。这样模型供应商要升级、参数要调整时只改一个文件就行。3. 提示词工程是地基不是玄学3.1 提示词的结构化方法把模糊需求变成明确的指令很多人觉得提示词工程就是“说话艺术”写几句“请帮我做一个……”就行。实际做工程时这套行不通。对生产系统来说提示词必须结构化通常分成四个部分角色与目标明确告诉模型它是什么、要完成什么输入格式约定告诉模型会收到什么数据、什么字段输出格式约束强制要求JSON、Markdown或特定字段结构边界与兜底当信息不足、出现未知情况时该怎么回应。举个例子我做一个信息抽取Agent时核心提示词是这样组织的你是一个信息抽取专家。用户会提供一段文本你需要抽取其中的结构化信息。 输入格式 - 文本从text开始到/text结束。 输出要求 - 只输出JSON对象不要输出任何其他文字。 - JSON必须包含字段title、date、author、summary。 - 如果文本中缺少某个字段该字段值为null。 边界规则 - 只抽取文本中明确出现的信息不要猜测。 - 文本为空或无可抽取信息时输出{error: no_info}。这样写完之后模型的输出就会非常稳定很少跑偏。关键不是措辞多么优雅而是每一个边界条件都清楚。3.2 上下文管理与Token预算别让对话无限膨胀提示词工程里另外一个大坑是上下文管理。很多人做Agent时把整个对话历史一股脑塞给模型结果上下文窗口很快被占满费用也飙升。我常用的策略有三个层次窗口滑动只保留最近N轮对话摘要压缩把更早的对话喂给模型生成一段摘要再把摘要放进系统提示词结构化裁剪把历史记录按“用户意图”“系统回答”“工具结果”分类只保留关键字段。具体选择哪个策略取决于业务容忍度。比如做客服机器人用户最近两轮意图最重要滑动窗口就够了做复杂任务编排则需要摘要压缩来保留长期上下文。Token预算还有一个量化技巧在做长文本任务时先估算输入文本的Token数再反推max_tokens是否够用。通常中文一个汉字大约是1到1.5个Token英文一个词约1.3个Token。如果max_tokens设置太小生成的回答会被截断导致JSON解析失败——这是高频bug。3.3 提示词的版本管理与回归测试这一节我想特别强调提示词应该像代码一样纳入版本管理。Git里每个commit都对应一种提示词版本并用评测集来检验提示词改动是否导致效果退化。我见过最惨的案例是同事在某次优化里把提示词的“不要输出多余文字”删掉了结果所有接口返回的JSON前面多了一行解释性文本下游解析全部报错。没有任何测试能拦住这种问题。后来我们做了一个简单的回归机制每个提示词版本跑同一套评测集至少对比“成功解析率”和“字段准确率”两个指标。所以从工程第一天起就要有“提示词即代码”的意识把它当作产品的一部分来对待。这大概是AI工程里最重要、也最容易被忽略的实践。4. 从零搭建一个可落地的AI Agent项目4.1 项目需求定义找到一个不会“空转”的场景讲完基础我们正式动手。为了不空转我选一个非常典型的需求作为例子做一个支持联网搜索、能够回答信息性问题的AI助手Agent。这个需求包含Agent的核心要素——调用外部工具、组织回答、处理失败情况。需求定义阶段要问自己三个问题用户的输入是什么形态纯文本问题输出是什么形态回答加引用来源中间需要调用哪些工具搜索API、知识库检索、网页内容抓取把这些问题写清楚后面代码实现就有边界了。4.2 Agent核心循环规划、调用工具、观察、反思Agent最核心的部分是一个循环。最简单但也最实用的循环是把用户问题发给模型附带可用的工具列表模型决定是直接回答还是调用某个工具如果调用工具系统执行对应函数把结果回传给模型模型根据工具结果生成最终回答或者决定再调一次工具。这个循环要用代码实现其实不难。下面是我用过的极简实现不含复杂框架核心逻辑不到一百行from openai import OpenAI client OpenAI() TOOLS { web_search: web_search_func, get_weather: get_weather_func, } def run_agent(user_query, max_steps5): messages [{role: user, content: user_query}] for _ in range(max_steps): response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, tools[tool_schema(web_search), tool_schema(get_weather)], tool_choiceauto, ) msg response.choices[0].message if not msg.tool_calls: return msg.content messages.append(msg) for call in msg.tool_calls: result TOOLS[call.function.name](**call.function.arguments) messages.append({ role: tool, tool_call_id: call.id, content: result, }) return 达到最大步数任务终止这个实现的关键点在于模型返回的tool_calls里包含了函数名和JSON格式参数我们要解析出来并真实执行把执行结果以role为tool的消息回传。很多新手在第二步就卡住了因为没有正确回传tool_call_id导致API报错。另一个容易忽略的点是max_steps限制。没有这层限制Agent可能会在一个问题上反复调用几十次工具成本完全失控。加一个步数上限是工程化兜底的第一步。4.3 让Agent拥有记忆从零开始实现会话管理真实的Agent不可能每个问题都无状态地从头开始。比如用户先问“北京今天的天气怎么样”再问“那明天呢”如果没有记忆第二个问题就完全无法回答。所以我们需要会话历史。工程上最简单的做法是持久化messages列表把它们存在内存或数据库里class Session: def __init__(self, session_id): self.session_id session_id self.history [] def add(self, role, content): self.history.append({role: role, content: content}) def get_messages(self, max_history10): return self.history[-max_history:]这里同样要配合上面说的上下文管理策略。如果历史长度超过阈值就调用一次摘要模型把旧历史压缩成一句话的摘要放进系统提示词里。这一步是Agent能“记住大事、忘掉细节”的关键。4.4 接入真实数据源把工具函数变成可复用的服务到这里Agent的骨架已经能跑了但想要它真正有用还得接入真实数据源。以搜索工具为例我会写成这样def web_search_func(query, top_k3): # 调用搜索API response search_client.search(query, top_ktop_k) results [] for item in response.results: results.append({ title: item.title, url: item.url, snippet: item.snippet, }) return json.dumps(results, ensure_asciiFalse)注意几个细节工具返回值一定是字符串因为API要求content必须是文本不要把原始对象直接传回给模型因为模型不认识Python对象工具内部要做异常捕获搜索接口超时或报错时返回明确错误信息而不是让整个Agent崩溃。实测下来把工具调用设计成“输入JSON、输出JSON字符串”Agent的稳定性会高很多。因为模型只跟字符串打交道天然避免了序列化问题。5. 实战中踩过的坑常见问题与排查技巧实录5.1 输出“发疯”与“过于保守”的平衡问题Agent跑起来之后最常遇到的问题就是模型行为在两个极端间摆动。一种情况是模型“太自由”会在回答里加入跟业务无关的内容甚至在JSON后面补贴一段“备注”。排查思路很简单先检查提示词里有没有明确的输出格式约束再看解析代码有没有宽容处理。另一种情况是模型“太保守”遇到稍微模糊的输入就开始道歉说“我无法确定您的问题”整个Agent形同虚设。这种情况多半是提示词里的“规避风险”措辞写得太重了。我的经验是边界规则要写在明处但语气要中性别让模型养成“一有不确定就拒绝”的坏习惯。5.2 工具调用出错JSON解析失败与参数幻觉工具调用是Agent项目最高频的出错点我统计过大概有三类模型返回的JSON里多了注释或逗号直接json.loads失败——解决方法是先在工具函数里做一次宽松解析模型生成了不存在的函数名比如写成了“search_web”而不是“web_search”——解决方法是把工具列表固化到提示词里并在执行前校验白名单模型“编造”参数尤其是日期、ID这些完全不是用户输入过的值——这是幻觉问题只能靠增加工具输入约束并在评测集里做敏感提醒。5.3 上下文越来越长导致的性能与费用失控Agent跑多轮之后上下文越来越长费用翻倍、响应变慢这是所有做过Agent工程的人都躲不开的问题。我分享一个快速评估方法打开日志查看每轮的输入Token数走势。如果每轮都比上一轮多几千Token说明上下文管理没有生效。最有效的截断手段一是上面提到的滑动窗口二是把工具返回的长文本做摘要。搜索API经常返回大篇幅费文直接把原文塞进去又贵又容易超窗应该让模型先提取关键信息再使用。5.4 模型升级导致的行为突变用了大半年老模型某天供应商通知要升级模型版本结果整个Agent行为大变原来稳定输出的JSON格式带上了多余换行原来会调工具的情况突然不调了。这不是你的代码出了问题而是模型行为漂移。应对方法是升级前一定要跑一遍离线评测集对比新旧版本在每个指标上的差异。不要盲目升级更不要在生产环境直接切流量。如果新版本整体效果更好但个别场景退化可以考虑用路由策略让不同场景走不同模型。6. 从Demo到可维护的AI服务体系6.1 让AI应用具备基础的可观测性Demo能跑通之后下一步一定是可观测性。我指的不仅是打日志而是把每次请求的关键信息记录下来包括用户输入、模型输出、工具调用次数、各环节耗时、Token消耗、最终是否成功。我用过最简单的方案是结构化JSON日志每个请求一条{ session_id: abc123, query: 北京今天天气怎么样, steps: 2, tools_used: [web_search], input_tokens: 1200, output_tokens: 300, duration_ms: 3400, success: true }有了这个日志你就能回答最基础的问题今天成功率多少、平均延迟多少、哪个工具调用最贵。没有这些数据优化和排障全是猜谜。6.2 离线评测集让每一次改动都有据可依AI工程里最容易被忽视的就是评测。没有评测集改提示词和改代码都像是在盲飞。一个合格的评测集至少要有几十上百条真实或接近真实的用户问题并标注期望行为。评测指标不必复杂初期用两个就够过程指标工具调用成功率、解析成功率、单次耗时结果指标人工打分或LLM-as-a-Judge打分。LLM-as-a-Judge就是用另一个更可靠的模型来评估输出质量但要注意不要让被评测的模型给自己打分这会有偏差。我们在项目里就吃过这个亏同一个模型既生成答案又评估自己的答案分数虚高得离谱后来改成用不同模型做裁判分数才贴近真实水平。6.3 快速上线的灰度策略先小流量再放开最后聊一下上线策略。AI应用跟传统应用有个很大的区别你没法保证模型在真实流量里的表现即使评测集全过线上还是可能有新花样。所以一定要灰度。我常用的做法是先放10%流量到新版本对比新旧版本在成功率、耗时的差异并且每天抽看人工反馈。稳定跑几天再逐步放开。一旦发现异常成功率下降、用户投诉增多立即切回旧版本。这套流程不需要复杂平台用简单的配置开关就能实现。最后再分享一点个人的体会做AI工程这一年多我最大的体会是这个领域的门槛不在技术而在“把不确定性当成常态来设计系统”的心态。你写出的代码面对的不是一个确定执行的函数而是一个有时候聪明、有时候犯傻的“合作者”。所以每一层都要加防护、加校验、加兜底。如果你正准备从零做一个AI项目我的建议很简单别急着上框架先把一个最小闭环跑通——模型调用、工具调用、结果返回——然后在这个闭环上慢慢加东西。框架能帮你加速但无法替代你对系统每一环节的理解。等你把一个裸的Agent调教到稳定输出再回头看那些开源Agent框架你会发现自己已经能看懂它们的每一个设计选择了。那时候你才算真正入了AI工程的门。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑